0

如果我随机生成 40 亿个 IP 地址,并将它们写入文本文件,则需要相当长的时间。你们有更好的主意来更快地完成这个动作吗?

这是我的代码

$ip_long = array(

            array('607649792', '608174079'), //36.56.0.0-36.63.255.255

            array('1038614528', '1039007743'), //61.232.0.0-61.237.255.255

            array('1783627776', '1784676351'), //106.80.0.0-106.95.255.255

            array('2035023872', '2035154943'), //121.76.0.0-121.77.255.255

            array('2078801920', '2079064063'), //123.232.0.0-123.235.255.255

            array('-1950089216', '-1948778497'), //139.196.0.0-139.215.255.255

            array('-1425539072', '-1425014785'), //171.8.0.0-171.15.255.255

            array('-1236271104', '-1235419137'), //182.80.0.0-182.92.255.255

            array('-770113536', '-768606209'), //210.25.0.0-210.47.255.255

            array('-569376768', '-564133889'), //222.16.0.0-222.95.255.255

        );

        $rand_key = mt_rand(0, 9);

        $handle = fopen('ip_data.dat', 'a+');
        for ($i=0; $i<4000000000; $i++) {
            $ip= long2ip(mt_rand($ip_long[$rand_key][0], $ip_long[$rand_key][1]));
            fwrite($handle, decbin( ip2long( $ip )) . "\r\n");

        }
4

3 回答 3

5

由于您确定的范围有限,您可以生成的不同值的总数大大小于 40 亿(取决于 的值$rand_key,它只评估一次,它永远不会超过大约 79*256*256 ~ 5M ) - 所以你会得到很多重复。在这种情况下,如果您生成一个字符串数组,您会快得多 - 一个字符串对应范围内的每个有效 IP 地址。然后从该列表中选择一个随机字符串并将其附加到一个字符串中。当字符串达到典型的块大小时写入字符串,将其设置回""并重复。

更重要的是,我质疑它的使用是否明智decbin- 它会将您的 IP 字符串变成许多 1 和 0,因此一个简单的 IP 地址将占用 32 个字节(加上\r\n34 个字节)。乘以4G,你就有120G+。这实际上比@Jon 在上面计算的 50 GB 数据要多得多……

如果您将 IP 地址存储为二进制数字,则每个数字只有四个字节 - 您也可以在此时关闭 CRLF。写得更快,读得更快。所以建议变成:

  1. 创建一个具有有效值范围的数组(这是一个整数范围;希望将它们视为无符号但不是 php 知道的类型)
  2. 从数组中选择一个随机值(随机索引)
  3. 将随机索引指向的值放入另一个数组(预定义大小 - 2048 个元素很好)
  4. 填充此数组时对其进行二进制写入
  5. 重复

你最终得到的是一个充满随机二进制数的文件,每个二进制数代表一个 IP 地址。它非常快(虽然它仍然需要编写一个 16G 的文件——但它已经尽可能小了)。

于 2013-07-12T15:27:49.320 回答
4

由于您正在写入 50GB 的数据,因此您的磁盘很可能是您的瓶颈。几点建议

  1. 停止频繁调用 fwrite - 建立大约 1000 个值,然后一次将它们全部写入,对 10000 个值尝试相同,测量性能
  2. 使用 C... 或更好的汇编
  3. 购买具有更高 RPM 或固态内存的硬盘
于 2013-07-12T15:24:59.073 回答
0

不要在循环中运行繁重的函数。增加一个变量然后写入一次会好得多。请注意,您在示例中编写的数据量仍然非常庞大,因此我选择猜测它只是一个“巨大”的数字,以便在尝试调整函数时真正显示时间差异。

$ip_long = array(

        array('607649792', '608174079'), //36.56.0.0-36.63.255.255

        array('1038614528', '1039007743'), //61.232.0.0-61.237.255.255

        array('1783627776', '1784676351'), //106.80.0.0-106.95.255.255

        array('2035023872', '2035154943'), //121.76.0.0-121.77.255.255

        array('2078801920', '2079064063'), //123.232.0.0-123.235.255.255

        array('-1950089216', '-1948778497'), //139.196.0.0-139.215.255.255

        array('-1425539072', '-1425014785'), //171.8.0.0-171.15.255.255

        array('-1236271104', '-1235419137'), //182.80.0.0-182.92.255.255

        array('-770113536', '-768606209'), //210.25.0.0-210.47.255.255

        array('-569376768', '-564133889'), //222.16.0.0-222.95.255.255

    );

    $rand_key = mt_rand(0, 9);

    $ip = '';
    for ($i=0; $i<40000; $i++) {
        $ip .= decbin( ip2long( long2ip(mt_rand($ip_long[$rand_key][0], $ip_long[$rand_key][1])))) . "\r\n";
    }
    $handle = fopen('ip_data.dat', 'a+');
    fwrite($handle, $ip);
于 2013-07-12T15:27:51.077 回答