• 两种语言“争霸赛”,PHP速度领先C#


    译者 | 张洁

    责编 | 屠敏

    有人的地方就有江湖,有江湖的地方就有纷争。提起编程语言话题,总会有人想要不甘示弱地争论一番。这不,就在一位名为@withinboredom的开发者发布的一条“我最喜欢的语言已由C#更改为PHP”的帖子下面,就有人表示了不服。

    @withinboredom在帖子中是这样描述的:“当你对PHP和C#这两种语言进行实际的基准测试时,会在一些实例中发现PHP的性能优于C#。”

    而用户@No McNoington却反驳道:“你有本事就展示代码示例,这样我就可以证明为什么你是错的。”

    @withinboredom回怼到:“这个人(@No McNoington)连个像样的笔名都懒得起,那就准备好被轰走吧!”

    PHP和C#在读取文件方面的较量

    @withinboredom首先展示的,是他认为“对每种语言都相当公平”的读取文件代码:PHP和C#将同步、逐字节地读取一个4Mib大小的文件。让我们看看PHP和C#在读取文件方面的较量吧!

    PHP :

    1. function test()
    2. {
    3. $file = fopen("/file/file.bin", 'r');
    4. $counter = 0;
    5. $timer = microtime(true);
    6. while ( ! feof($file)) {
    7. $buffer = fgets($file, 4096);
    8. $counter += substr_count($buffer, '1');
    9. }
    10. $timer = microtime(true) - $timer;
    11. fclose($file);
    12. printf("counted %s 1s in %s milliseconds\n", number_format($counter), number_format($timer * 1000, 4));
    13. }
    14. test();

     C#:

    1. using System.Diagnostics;
    2. using System.Text;
    3. var test = () => {
    4. using var file = File.OpenText("/file/file.bin");
    5. var counter = 0;
    6. var sw = Stopwatch.StartNew();
    7. while(!file.EndOfStream)
    8. {
    9. if(file.Read() == '1')
    10. {
    11. counter++;
    12. }
    13. }
    14. sw.Stop();
    15. Console.WriteLine($"Counted {counter:N0} 1s in {sw.Elapsed.TotalMilliseconds:N4} milliseconds");
    16. };
    17. test();

    “读取文件几乎不包含用户级代码,只是单纯测试一种语言的基本功能。”@withinboredom还补充道,代码中添加计数只是为了防止PHP或C#中的编译器擅自优化或删除代码,并无其他作用。

    然而,有些开发者对这个测试反驳道:“PHP并没有一个字节一个字节地读取文件啊(PHP中的fgets()函数用于从文件中读取一行)!”@withinboredom火速回怼:“可C#也不是逐个字节读取的!理论上读取方式是一样的。”

    以下是两种语言在读取4Mib文件下的对比结果:

    PHP:32.49毫秒(平均超过10次运行)

    C#:37.30毫秒(平均超过10次运行)

    4Mib大概只是一张完整照片的大小,所以为了进一步证明PHP的优越,@withinboredom还测试了这两种语言读取2.5g视频大小的文件速度:

    PHP:24.82秒(平均超过10次运行)

    C#:26.67秒(平均超过10次运行)

    综上可以得出,不论是4Mib还是2.5g文件,PHP在读取文件速度方面都优于C#。

    函数调用开销是“罪魁祸首”?

    很多开发者认为这是由于C#没有以二进制模式读取文件,其中函数调用开销是罪魁祸首。然而,@withinboredom表示,在函数调用方面, C#比PHP快很多个数量级,所以问题不在于此。以下是2.5gb文件中二进制模式的代码:

    1. using System.Diagnostics;
    2. using System.Text;
    3. var binTest = () =>
    4. {
    5. using var file = File.OpenRead("/file/file.bin");
    6. var counter = 0;
    7. var buffer = new byte[4096];
    8. var numRead = 0;
    9. var sw = Stopwatch.StartNew();
    10. while ((numRead = file.Read(buffer, 0, buffer.Length)) != 0)
    11. {
    12. counter += buffer.Take(numRead).Count((x) => x == '1');
    13. }
    14. sw.Stop();
    15. Console.WriteLine($"Counted {counter:N} 1s in {sw.Elapsed.TotalMilliseconds} milliseconds");
    16. };
    17. binTest();

    考虑到有人认为会是Linq(语言集成查询)的问题,@withinboredom删除了.Take和重复计数的相关代码:

    有.Take:38.40s(2.5gb文件)

    没有.Take:23.5s(2.5gb文件——错误的实现)

    关于查看文件性能的测试

    因为一些开发者想优化C#而不优化PHP,所以@withinboredom设计了下面只查看文件性能的测试,供开发者参考。

    PHP:

    1. function test()
    2. {
    3. $file = fopen("/file/file.bin", 'r');
    4. $counter = 0;
    5. $timer = microtime(true);
    6. while (stream_get_line($file, 4096) !== false) {
    7. ++$counter;
    8. }
    9. $timer = microtime(true) - $timer;
    10. fclose($file);
    11. printf("counted %s 1s in %s milliseconds\n", number_format($counter), number_format($timer * 1000, 4));
    12. }
    13. test();

    C#:

    1. var binTest = () =>
    2. {
    3. using var file = File.OpenRead("/file/file.bin");
    4. var counter = 0;
    5. var buffer = new byte[4096];
    6. var sw = Stopwatch.StartNew();
    7. while (file.Read(buffer, 0, buffer.Length) != 0)
    8. {
    9. counter += 1;
    10. }
    11. sw.Stop();
    12. Console.WriteLine($"Counted {counter:N} 1s in {sw.Elapsed.TotalMilliseconds} milliseconds");
    13. };
    14. binTest();

    经测试,结果如下:

    PHP:423.50毫秒(平均超过10次运行)

    C#:530.42毫秒(平均超过10次运行)

    据@withinboredom介绍,PHP和C#之间的性能差异是他在去年发现的。当时他正巧在将一些杂七杂八的文件转移至Dapr(分布式应用程序)和Kubernetes,结果无意中发现:在读取文件方面,PHP居然比C#更快!

    尽管@withinboredom表示目前他最爱的编程语言已变为PHP,但这并不代表C#开发者就要为此放弃一切,用PHP(或更好的C)重写所有文件的编写内容:“几毫秒的差距是不会毁掉开发者的。”

    原文链接:Yes, PHP is faster than C# – A Walk Within Boredom

  • 相关阅读:
    [Kettle] 公式
    【c++】——类和对象(中)——实现完整的日期类(优化)万字详细解疑答惑
    一次性搞懂长轮询、短轮询、SSE、websocket区别
    NLC: Search Correlated Window Pairs on Long Time Series(VLDB2022)
    GitHub构建Maven依赖仓库
    一文搞定vim,从安装到入门到精通,助你成功入门vim
    关于 国产麒麟系统Qt强制退出应用程序qApp->exit()无效 的解决方法
    10.5作业
    Java基础面试题
    Swin Transformer与Vision Transformer的区别与联系
  • 原文地址:https://blog.csdn.net/csdnnews/article/details/123664613