V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kankana
V2EX  ›  PHP

php vs python 写文件对比

  •  
  •   kankana · 2016-03-15 22:28:36 +08:00 · 5010 次点击
    这是一个创建于 2969 天前的主题,其中的信息可能已经有所发展或是发生改变。

    吐个槽, 顺便记录.

    结论: php 完败

    有个项目:

    1, 客户提供数据,

    2, 生成新的文本

    3, 将文本写入磁盘, 大概 5kb 左右

    客户抱怨文件生成速度太慢了. 有时候, 需要生成上万个文件.

    花了点时间, 将 2 的处理方法, 单独抽出来, 并转成 python. 分别测试...

    2 这个过程, 循环 10000 次, php 和 python 花的时间都差不多, 在 35s 左右.

    在这 10000 次循环里, 又加上了 3, 每次循环都会写文件. 注意,每次文件内容都是不同的.

    python 在 2 的时间基础上, 多了 2, 3 秒. 试了 with open 和 f = open, f.write, f.close 两种方法, 都差不多

    php 则多了 10 多秒. 试了 file_put_contents 和 fopen, fwrite, fclose....

    不信邪, 研究了一晚上的 php 扩展

    // php_stream *stream;
    char *filename;
    int filename_len = 0;
    char *data;
    long data_len = 0;
    // long numbytes = 0;
    FILE *fp;
    
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ps", &filename, &filename_len, &data, &data_len) == FAILURE)
        return;
    
    fp = fopen(filename, "w");
    fwrite(data, data_len, 1, fp);
    fclose(fp);
    
    // stream = php_stream_open_wrapper_ex(filename, "w", 0, NULL, NULL);
    //    numbytes = php_stream_write(stream, data, data_len);
     //    php_stream_close(stream);`
     RETURN_LONG(data_len);
    

    `

    都这么短了, 速度能快点了吗... 直接破 50s, 现在浏览器还显示57.454752206802

    无语了...

    还试过 swoole 的 swoole_async_writefile, 写入文件超级快的... 只是很快 too many open files, 进程挂掉

    第 1 条附言  ·  2016-03-16 10:34:38 +08:00

    傻逼傻逼了.....

    这次都是 vagrant 里面做的测试,

    这次只是纯粹测试写文件了, 10w 个文件. 文件大小 4.4kb 左右

    每个脚本测试两次, 测试前先清空目录, 测试完, 统计文件数目是否 10w.秒为单位

    python

    result = generate_article()
    
    a = datetime.now()
    
    i = 100000
    
    while (i > 0):
        filename = "articles/" + str(i) + ".txt"
        f = open(filename, 'w')
        f.write(result)
        f.close()
        i = i-1
    
    b = datetime.now()
    c = b - a
    

    python

    php, 自写的扩展, 代码参考上面的, 别被 "mass_"名字误导了, 不是批量的意思, 这是项目的简称而已

    $result = generate_article();
    $a = microtime(true);
    
    $i = 100000;
    while ($i > 0) {
    
        $filename = "articles/$i.txt";
        mass_file_put_contents($filename, $result);
        $i = $i - 1;
    }
    
    $b = microtime(true);
    
    
    echo $b - $a;
    

    test_mass_file_put_contents

    php 的 file_get_contents

    $result = generate_article();
    $a = microtime(true);
    
    $i = 100000;
    while ($i > 0) {
    
        $filename = "articles/$i.txt";
        file_put_contents($filename, $result);
        $i = $i - 1;
    }
    
    $b = microtime(true);
    

    test_file_put_contents

    结论. php 落后一点. 扩展也不是没有帮助, 你们看下 file_put_contents 的源代码, 再和我的对比下.

    第 2 条附言  ·  2016-03-16 11:16:27 +08:00

    在实际环境中, 需要在一个(几百次,几千,甚至上万次)循环中, 根据用户提供的数据 不断生成新文件, 并写入磁盘, 这个过程有时候很慢.

    由于我们使用 redis 做队列. 于是我就琢磨着, 试下其他语言, 让它们来处理这些 io 频繁的任务.

    于是就有了主题贴的乌龙测试... 还以为 php 在文件写入这块真的比不了 python.... 原来我是来 host 上的 python 和 vagrant 里的 php 对比

    第一个补充贴, 纠正了这个错误, 而且是单纯的写入对比.

    下图, 则是, 真实场景应用, 在循环里, 生成新文件并写入磁盘, 5000 次

    real test

    php 不愧是最好的语言!!!

    现在学学如何应用 pthreads 到我这个用例上... 8 核 cpu 不能浪费

    第 3 条附言  ·  2016-03-17 20:46:25 +08:00
    啊, 大家别说什么打脸不打脸... 不好听. 谁没犯错的时候呢... 就这简单测试, 我一连犯了好几次失误.

    1, python 是命令行下运行, php 则是在浏览器运行(php5-fpm)

    2, python 在 host 上, php 在 vagrant

    3, 测试的次数不够多. 2 次, 10 次, 数量级也不够大, 说明不了什么.

    后来,我才发现瓶颈, 其实就是在"生成新文本"这个步骤, 用户提供的数据量太大了...

    写文件, 看起来 python 和 php 差距并不大

    通过这次探索, 还是学到了点东西的.
    18 条回复    2016-03-17 08:46:26 +08:00
    iyaozhen
        1
    iyaozhen  
       2016-03-15 23:14:43 +08:00   ❤️ 1
    你单个目录文件写的太多了吧。 ext3 文件系统一级子目录文件数有限制( 32000 )。搞个二级目录,速度绝对能上去。

    你写扩展没啥意义,底层都是 C 。
    还有 swoole_async_writefile 只是异步写,还是会有一级子目录文件数的限制,以及文件系统的其它一些限制。
    jhdxr
        2
    jhdxr  
       2016-03-16 00:37:21 +08:00
    测试不贴代码。。。
    bombless
        3
    bombless  
       2016-03-16 00:47:20 +08:00 via Android
    试试 PHP7 吧。
    其实你拿 py 出来比很不利,我们拿 rust 出来比看是你 py 的几倍(逃

    (明天回公司了给你对比下
    mko0okmko0
        4
    mko0okmko0  
       2016-03-16 01:54:49 +08:00   ❤️ 1
    1.你没用多核心设计吃满 CPU 跟 IO 资源.
    2.java 跟 C#(mono)是好东西,可以帮你搞定 1.
    3.使用 swoole 看是否加上计数锁避免爆发量太大.建议(CPU 核心数+硬碟数量)x2
    我不是程式语言狂热者,是遇过类似的蛋疼竞赛被坑很惨.
    ershisi
        5
    ershisi  
       2016-03-16 08:45:54 +08:00
    python 打开文件描述符和关闭文件描述符比较快吗?不清楚 python 的底层实现。你拿 php 扩展出来说事是没有价值的--!因为它还是封装了 c 的底层。想来应该是在封装的时候对文件描述符的判断比较多。所以在写的时候回占用一定的时间吧?
    tabris17
        6
    tabris17  
       2016-03-16 09:13:33 +08:00
    你都没搞明白瓶颈在哪里
    kankana
        7
    kankana  
    OP
       2016-03-16 09:48:11 +08:00
    的确不知道瓶颈在哪里, 为毛写文件这么慢呢?

    php 扩展也是我最后能想到的方法, 试试呗, 我也没搞过扩展, 失败了也权当是学习了.

    对了, 用的是 php 5.6.17, 跟生产环境一样. 等等我在测试下, 现在才想到是 php 是在 vagrant 里运行, python 是在 host 上.....
    kankana
        8
    kankana  
    OP
       2016-03-16 09:54:52 +08:00
    `
    stream = php_stream_open_wrapper_ex(filename, "w", 0, NULL, NULL);
    numbytes = php_stream_write(stream, data, data_len);
    php_stream_close(stream);
    `

    顺便说下, 这三行是 file_put_contents 源代码提取出来的. 我以为 php_stream*是 php 自己封装的, 用 fopen, fwrite, fclose, 会比较快点, 其实并没有....
    lovedboy
        9
    lovedboy  
       2016-03-16 11:09:45 +08:00
    有没有考虑过是 buffer 的原因, Python 的 IO buffer 比 php 的大?
    realpg
        10
    realpg  
       2016-03-16 11:19:40 +08:00
    不用看就知道 php 会大幅落后 python
    专业的东西干专业的事儿, PHP 就是用来处理基本 web 请求的,这种东西,写个 java/c 值守程序最好, python 也可以干这个只是效率会比 java/c 低一些
    BOYPT
        11
    BOYPT  
       2016-03-16 11:20:53 +08:00
    基本涉及磁盘 IO 的,语言之间不应该有太大区别。
    iyaozhen
        12
    iyaozhen  
       2016-03-16 12:21:32 +08:00 via Android
    @BOYPT 是的,这种场景没多大区别。只有实现的区别。
    msg7086
        13
    msg7086  
       2016-03-16 13:07:31 +08:00
    写文件的时候先开 iostat 看一下写入情况。
    如果是总写入速度不高,那可能是文件系统的锅,试试 reiser4 之类的黑科技。
    wingoo
        14
    wingoo  
       2016-03-16 13:51:59 +08:00
    php 的读文件曾经测试过, 和 python 时间差不多
    几百兆上 G 的文件

    但 array 处理太慢了, 之前项目需求, 数组里大概上百万个 key, 比 python 慢了几十倍吧
    situs
        15
    situs  
       2016-03-16 14:23:18 +08:00
    一场血雨腥风。。。
    jhdxr
        16
    jhdxr  
       2016-03-16 22:40:06 +08:00
    @realpg 看补充,被打脸了 233333
    一个语言,如果它的执行时间差距,能比 IO 还要大(或者一个量级),那这语言得有多失败
    jhdxr
        17
    jhdxr  
       2016-03-16 22:46:45 +08:00
    @wingoo php 全是 map ,处理不好的确容易悲剧。。。
    firebroo
        18
    firebroo  
       2016-03-17 08:46:26 +08:00 via Android
    看到楼上有人被打脸,如果楼主用了 PHP7 的测试对比,估计楼上有人脸都要肿成狗了, PHP 是 web 的 c 语言,你以为真是大家随便说的-_-||
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2256 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 02:46 · PVG 10:46 · LAX 19:46 · JFK 22:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.