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

PHP 跑 Python 比 Python 更快!

  •  1
     
  •   mrpzx001 · 2023-12-08 13:18:50 +08:00 · 3041 次点击
    这是一个创建于 380 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原文

    https://github.com/swoole/phpy/blob/main/docs/benchmark.md

    压力测试

    压测脚本中创建了一个 PyDict ,分别读写 PHP 代码和 Python 代码执行 1000 万次

    • PHP 版本PHP 8.2.3 (cli) (built: Mar 17 2023 15:06:57) (NTS)
    • Python 版本Python 3.11.5
    • 操作系统:Ubuntu 20.04
    • GCC 版本gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)

    请注意设需要构造一个 1000 万个元素的 HashTable,需要至少 2G 以上内存空间才可以运行此测试

    PHP

    <?php
    
    $dict = new PyDict();
    const COUNT = 10000000;
    
    $n = COUNT;
    $s = microtime(true);
    while ($n--) {
        $dict['key-' . $n] = $n * 3;
    }
    echo 'dict set: ' . round(microtime(true) - $s, 6) . ' seconds' . PHP_EOL;
    
    $c = 0;
    $n = COUNT;
    $s = microtime(true);
    while ($n--) {
        $c += $dict['key-' . $n];
    }
    echo 'dict get: ' . round(microtime(true) - $s, 6) . ' seconds' . PHP_EOL;
    

    Python

    import time
    
    my_dict = {}
    COUNT = 10000000
    
    n = COUNT
    start_time = time.time()
    
    
    for i in range(n):
        my_dict["key-" + str(i)] = i * 3
    
    elapsed_time = time.time() - start_time
    
    print(f"dict set: {elapsed_time:.6f} seconds")
    
    n = COUNT
    
    total = 0
    start_time_get = time.time()
    for i in range(n):
        total += my_dict["key-" + str(i)]
    
    elapsed_time_get = time.time() - start_time_get
    
    print(f"dict get: {elapsed_time_get:.6f} seconds")
    

    PHP 数组

    <?php
    
    ini_set('memory_limit', '2G');
    $dict = [];
    const COUNT = 10000000;
    
    $n = COUNT;
    $s = microtime(true);
    while ($n--) {
        $dict['key-' . $n] = $n * 3;
    }
    echo 'array set: ' . round(microtime(true) - $s, 6) . ' seconds' . PHP_EOL;
    
    $c = 0;
    $n = COUNT;
    $s = microtime(true);
    while ($n--) {
        $c += $dict['key-' . $n];
    }
    echo 'array get: ' . round(microtime(true) - $s, 6) . ' seconds' . PHP_EOL;
    

    结果对比

    (base) htf@swoole-12:~/workspace/python-php/docs/benchmark$ php dict.php 
    dict set: 4.663758 seconds
    dict get: 3.980076 seconds
    (base) htf@swoole-12:~/workspace/python-php/docs/benchmark$ php array.php 
    array set: 1.578963 seconds
    array get: 0.831129 seconds
    (base) htf@swoole-12:~/workspace/python-php/docs/benchmark$ python dict.py 
    dict set: 5.321664 seconds
    dict get: 4.969081 seconds
    (base) htf@swoole-12:~/workspace/python-php/docs/benchmark$
    

    Python 测试为基准:

    脚本名称 Set Get
    dict.php 114% 125%
    array.php 337% 599%
    • phpyPHP 代码写入 PyDict 的性能比原生 Python14%,读取性能高 25%
    • PHP 写入 PHP Array 的性能比 Python 写入 Dict237%,读取高出了近 500%

    其他

    phpy 这个项目已经进化到可以调用任何 python 内置常量、函数、模块,包括 print 、compile 、eval 、exec 等等,也就是说你完全可以用 php 的语法来写 python ,比如

    https://docs.python.org/zh-cn/3/library/ast.html#module-ast
    示例代码:print(ast.dump(ast.parse('x = 1'), indent=4))
    
    php 写法:
    $py = PyCore::import('builtins');
    $ast = PyCore::import('ast');
    $py->print($ast->dump($ast->parse('x = 1'), indent: 4));
    

    以上只是写着玩,phpy 的初衷是用 python 来弥补 php 生态上的不足,现在你可以用 php 来跑大模型了

    13 条回复    2023-12-09 13:04:19 +08:00
    ersic
        1
    ersic  
       2023-12-08 13:24:44 +08:00
    可是今天韩天峰刚说了,损耗在 50%左右
    mrpzx001
        2
    mrpzx001  
    OP
       2023-12-08 13:26:32 +08:00
    @ersic 他昨天测试的时候用的是 debug 版的 php ,性能当然差了
    aogg
        3
    aogg  
       2023-12-08 13:32:29 +08:00
    能不能用 python 的库,比如 gui 界面之类的,还有大模型的类库
    aogg
        4
    aogg  
       2023-12-08 13:35:50 +08:00
    不能支持多线程的原理是什么
    lambdaq
        5
    lambdaq  
       2023-12-08 13:40:18 +08:00   ❤️ 1
    凡事编程语言跑分,python 一看到 for 就直接宣布比赛结束了。
    lambdaq
        6
    lambdaq  
       2023-12-08 13:43:48 +08:00
    另外
    my_dict["key-" + str(i)] = i * 3

    改成

    my_dict["key-%s"% i] = i * 3

    我这里会从 5.6 秒变 4.6 秒。
    lambdaq
        7
    lambdaq  
       2023-12-08 13:45:31 +08:00
    换成 my_dict[b"key-%d"% i] = i * 3 变成 3.6 秒。

    结论:字符串是个体力活。
    mrpzx001
        8
    mrpzx001  
    OP
       2023-12-08 13:45:36 +08:00
    @aogg 能,轻轻松松跑起来 chatglm3 ,gui 更不在话下了,可以看 example
    mrpzx001
        9
    mrpzx001  
    OP
       2023-12-08 13:46:35 +08:00
    @aogg 不是不能,大佬没空而已,说不定哪天兴致来了就支持了
    NoOneNoBody
        10
    NoOneNoBody  
       2023-12-08 13:47:12 +08:00
    试试
    my_dict = {f"key-{i}": i*3 for i in range(n)}
    ...
    total = sum(my_dict.values())
    我没环境测试

    最想不通在无需过滤的情况下,求 total 为什么要跑个 for 累加器,抓着痛处打?
    encro
        11
    encro  
       2023-12-08 13:59:14 +08:00
    没达到一个数量级差别的优化,意义都不大。。。。
    lisxour
        12
    lisxour  
       2023-12-08 16:55:04 +08:00
    numpy 这类的库不是有专门的优化嘛,这能打得过?
    crackidz
        13
    crackidz  
       2023-12-09 13:04:19 +08:00
    这不是比了个寂寞...一到 Python 代码里面速度不就一样了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2765 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 09:04 · PVG 17:04 · LAX 01:04 · JFK 04:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.