譯者 | 張潔
責編 | 屠敏
有人的地方就有江湖,有江湖的地方就有紛爭。提起編程語言話題,總會有人想要不甘示弱地爭論一番。這不,就在一位名為@withinboredom的開發(fā)者發(fā)布的一條“我最喜歡的語言已由C#更改為PHP”的帖子下面,就有人表示了不服。
@withinboredom在帖子中是這樣描述的:“當你對PHP和C#這兩種語言進行實際的基準測試時,會在一些實例中發(fā)現(xiàn)PHP的性能優(yōu)于C#?!?/p>
而用戶@No McNoington卻反駁道:“你有本事就展示代碼示例,這樣我就可以證明為什么你是錯的?!?/p>
@withinboredom回懟到:“這個人(@No McNoington)連個像樣的筆名都懶得起,那就準備好被轟走吧!”
@withinboredom首先展示的,是他認為“對每種語言都相當公平”的讀取文件代碼:PHP和C#將同步、逐字節(jié)地讀取一個4Mib大小的文件。讓我們看看PHP和C#在讀取文件方面的較量吧!
PHP :
function test(){ $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#:
using System.Diagnostics;using System.Text;var test = () => { using var file = File.OpenText("/file/file.bin"); var counter = 0; var sw = 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還補充道,代碼中添加計數(shù)只是為了防止PHP或C#中的編譯器擅自優(yōu)化或刪除代碼,并無其他作用。
然而,有些開發(fā)者對這個測試反駁道:“PHP并沒有一個字節(jié)一個字節(jié)地讀取文件?。≒HP中的fgets()函數(shù)用于從文件中讀取一行)!”@withinboredom火速回懟:“可C#也不是逐個字節(jié)讀取的!理論上讀取方式是一樣的。”
以下是兩種語言在讀取4Mib文件下的對比結(jié)果:
PHP:32.49毫秒(平均超過10次運行)
C#:37.30毫秒(平均超過10次運行)
4Mib大概只是一張完整照片的大小,所以為了進一步證明PHP的優(yōu)越,@withinboredom還測試了這兩種語言讀取2.5g視頻大小的文件速度:
PHP:24.82秒(平均超過10次運行)
C#:26.67秒(平均超過10次運行)
綜上可以得出,不論是4Mib還是2.5g文件,PHP在讀取文件速度方面都優(yōu)于C#。
很多開發(fā)者認為這是由于C#沒有以二進制模式讀取文件,其中函數(shù)調(diào)用開銷是罪魁禍首。然而,@withinboredom表示,在函數(shù)調(diào)用方面, C#比PHP快很多個數(shù)量級,所以問題不在于此。以下是2.5gb文件中二進制模式的代碼:
using System.Diagnostics;using System.Text; var binTest = () =>{ using var file = File.OpenRead("/file/file.bin"); var counter = 0; var buffer = new byte[4096]; var numRead = 0; var sw = 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和重復計數(shù)的相關(guān)代碼:
有.Take:38.40s(2.5gb文件)
沒有.Take:23.5s(2.5gb文件——錯誤的實現(xiàn))
因為一些開發(fā)者想優(yōu)化C#而不優(yōu)化PHP,所以@withinboredom設(shè)計了下面只查看文件性能的測試,供開發(fā)者參考。
PHP:
function test(){ $file = fopen("/file/file.bin", "r"); $counter = 0; $timer = microtime(true); while (stream_get_line($file, 4096) !== false) { ++$counter; } $timer = microtime(true) - $timer; fclose($file); printf("counted %s 1s in %s milliseconds\n", number_format($counter), number_format($timer * 1000, 4));}test();
C#:
var binTest = () =>{ using var file = File.OpenRead("/file/file.bin"); var counter = 0; var buffer = new byte[4096]; var sw = Stopwatch.StartNew(); while (file.Read(buffer, 0, buffer.Length) != 0) { counter += 1; } sw.Stop(); Console.WriteLine($"Counted {counter:N} 1s in {sw.Elapsed.TotalMilliseconds} milliseconds");}; binTest();
經(jīng)測試,結(jié)果如下:
PHP:423.50毫秒(平均超過10次運行)
C#:530.42毫秒(平均超過10次運行)
據(jù)@withinboredom介紹,PHP和C#之間的性能差異是他在去年發(fā)現(xiàn)的。當時他正巧在將一些雜七雜八的文件轉(zhuǎn)移至Dapr(分布式應(yīng)用程序)和Kubernetes,結(jié)果無意中發(fā)現(xiàn):在讀取文件方面,PHP居然比C#更快!
盡管@withinboredom表示目前他最愛的編程語言已變?yōu)镻HP,但這并不代表C#開發(fā)者就要為此放棄一切,用PHP(或更好的C)重寫所有文件的編寫內(nèi)容:“幾毫秒的差距是不會毀掉開發(fā)者的?!?/p>
原文鏈接:Yes, PHP is faster than C# – A Walk Within Boredom
關(guān)鍵詞: