
點擊,查看本書教學大綱
譯者 | 張潔
責編 | 屠敏
有人的地方就有江湖,有江湖的地方就有紛爭。提起編程語言話題,總會有人想要不甘示弱地爭論一番。這不,就在一位名為@withinboredom的開發者發布的一條「我最喜歡的語言已由C#更改為PHP」的帖子下面,就有人表示了不服。
@withinboredom在帖子中是這樣描述的:「當你對PHP和C#這兩種語言進行實際的基準測試時,會在一些實例中發現PHP的性能優於C#。」
而用戶@No McNoington卻反駁道:「你有本事就展示代碼示例,這樣我就可以證明為什麼你是錯的。」

@withinboredom回懟到:「這個人(@No McNoington)連個像樣的筆名都懶得起,那就準備好被轟走吧!」

PHP和C#在讀取文件方面的較量
@withinboredom首先展示的,是他認為「對每種語言都相當公平」的讀取文件代碼:PHP和C#將同步、逐字節地讀取一個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還補充道,代碼中添加計數只是為了防止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文件中二進制模式的代碼:
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和重複計數的相關代碼:
有.Take:38.40s(2.5gb文件)
沒有.Take:23.5s(2.5gb文件——錯誤的實現)

關於查看文件性能的測試
因為一些開發者想優化C#而不優化PHP,所以@withinboredom設計了下面只查看文件性能的測試,供開發者參考。
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();經測試,結果如下:
PHP:423.50毫秒(平均超過10次運行)
C#:530.42毫秒(平均超過10次運行)
據@withinboredom介紹,PHP和C#之間的性能差異是他在去年發現的。當時他正巧在將一些雜七雜八的文件轉移至Dapr(分布式應用程序)和Kubernetes,結果無意中發現:在讀取文件方面,PHP居然比C#更快!
儘管@withinboredom表示目前他最愛的編程語言已變為PHP,但這並不代表C#開發者就要為此放棄一切,用PHP(或更好的C)重寫所有文件的編寫內容:「幾毫秒的差距是不會毀掉開發者的。」
原文鏈接:https://withinboredom.info/blog/2022/03/16/yes-php-is-faster-than-c/


掃描,優惠購書