如何以最快的速度将数据写入文本文件?

时间:2013-07-12 15:20:12

标签: php

如果我随机生成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");

        }

3 个答案:

答案 0 :(得分:4)

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

更重要的是,我怀疑使用decbin是多么明智 - 它会将您的IP字符串转换为许多1和0,因此一个简单的IP地址将占用32个字节(加\r\n,这是34)。乘以4G,你有120G +。实际上,这比@Jon在上面计算的50 GB还要多得多......

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

  1. 创建一个包含有效值范围的数组(这是一个整数范围;想要将它们视为无符号但不是php知道的类型)
  2. 从数组中选择一个随机值(随机索引)
  3. 将随机索引指向的值放入另一个数组(预定义大小 - 2048个元素是好的)
  4. 填写此数组时对该数组进行二进制写入
  5. 重复
  6. 你最终得到的是一个充满随机二进制数的文件,每个二进制数代表一个ip地址。它的速度非常快(虽然它仍然需要编写一个16G文件 - 但这个文件尽可能小)。

答案 1 :(得分:3)

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

  1. 停止经常调用fwrite - 建立大约1000个值,然后一次性写入它们,尝试使用10000个值,测量性能
  2. 使用C ...或更好的装配
  3. 购买具有更高RPM或固态内存的硬盘

答案 2 :(得分: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);