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

译者 | 张洁
责编 | 屠敏
有人的地方就有江湖 , 有江湖的地方就有纷争 。 提起编程语言话题 , 总会有人想要不甘示弱地争论一番 。 这不 , 就在一位名为@withinboredom的开发者发布的一条“我最喜欢的语言已由C#更改为PHP”的帖子下面 , 就有人表示了不服 。
@withinboredom在帖子中是这样描述的:“当你对PHP和C#这两种语言进行实际的基准测试时 , 会在一些实例中发现PHP的性能优于C# 。 ”
而用户@No McNoington却反驳道:“你有本事就展示代码示例 , 这样我就可以证明为什么你是错的 。 ”
@withinboredom回怼到:“这个人(@No McNoington)连个像样的笔名都懒得起 , 那就准备好被轰走吧!”
PHP和C#在读取文件方面的较量
@withinboredom首先展示的 , 是他认为“对每种语言都相当公平”的读取文件代码:PHP和C#将同步、逐字节地读取一个4Mib大小的文件 。 让我们看看PHP和C#在读取文件方面的较量吧!
PHP :

functiontest { $file= fopen( "/file/file.bin", 'r');$counter= 0;$timer= microtime( true);while( ! feof( $file)) {$buffer= fgets( $file, 4096);$counter+= substr_count( $buffer, '1');} $timer= microtime( true) - $timer;fclose( $file);printf( "counted %s 1s in %s milliseconds\n", number_format( $counter), number_format( $timer* 1000, 4));}test;C#:
usingSystem.Diagnostics;usingSystem.Text;vartest = => { usingvarfile = File.OpenText( "/file/file.bin"); varcounter = 0; varsw = Stopwatch.StartNew; while(!file.EndOfStream) {if(file.Read == '1') {counter++;}}sw.Stop;Console.WriteLine( $"Counted {counter:N0}1s in {sw.Elapsed.TotalMilliseconds:N4}milliseconds" ); };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文件中二进制模式的代码:
usingSystem.Diagnostics; usingSystem.Text; varbinTest = => {usingvarfile = File.OpenRead( "/file/file.bin"); varcounter = 0; varbuffer = newbyte[ 4096]; varnumRead = 0; varsw = Stopwatch.StartNew; while((numRead = file.Read(buffer, 0, buffer.Length)) != 0) {counter += buffer.Take(numRead).Count((x) => x == '1'); }sw.Stop;Console.WriteLine( $"Counted {counter:N}1s in {sw.Elapsed.TotalMilliseconds}milliseconds" ); };binTest;考虑到有人认为会是Linq(语言集成查询)的问题 , @withinboredom删除了.Take和重复计数的相关代码:

特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。