寫程式做下效能測試都是例行的事情了,一般在普通電腦上測試一下如果比較理想那基本不出什麼意外!但世事難料,程式碼寫得不好經常擔心CPU不夠用,其實寫得好但不能完全發揮出CPU資源的優勢更是一件悲劇的事情!這次事件已經發生了兩回,其實還真的很折磨人的。話不多說回到今天的正題Newtonsoft.Json
vs Protobuf.net
,對於兩者的效能我相信大部分人會站在Protobuf.net
這一邊,的確Protobuf.net
作為進位制序列化比JSON
文字的序列化要高效也是正常事情;但總會有些情況讓人難以預料的!接下來看一下測試情況
低置下測試
測試硬體:配置是E3-1230V2 測試用例:返回指定資料量的客戶列表資訊
Newtonsoft.Json
D:\>bombardier.exe -c 100 -n 10000000 http://192.168.2.18:8080/customers_json/3 Bombarding http://192.168.2.18:8080/customers_json/3 with 10000000 request(s) us ing 100 connection(s) 10000000 / 10000000 [==========================================] 100.00% 1m16s Done! Statistics Avg Stdev Max Reqs/sec 131290.96 14813.10 146691.93 Latency 757.08us 1.13ms 398.02ms HTTP codes: 1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 118.21MB/s
protobuf.net
D:\>bombardier.exe -c 100 -n 10000000 http://192.168.2.18:8080/customers_protobu f/3 Bombarding http://192.168.2.18:8080/customers_protobuf/3 with 10000000 request(s ) using 100 connection(s) 10000000 / 10000000 [===========================================] 100.00% 1m5s Done! Statistics Avg Stdev Max Reqs/sec 152160.79 14677.95 163191.02 Latency 653.08us 1.10ms 396.02ms HTTP codes: 1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 86.35MB/s
由於資料都是字元型別的欄位,所以Protobuf.net
在效能上並沒佔有多大的優勢,不過的確可以節省大量的頻寬,大概能節少40%的頻寬資源。其實從測試結果看來JSON處理也並沒有想像中那麼慢,效能差距在20-30%之間,其實還是可以接受的。
高配置下測試
既然在低配置的機器上Protobuf.net
有優勢,那高配置的伺服器按理也不會存在什麼問題。但測試結果告訴我們,Protobuf.net
輸給了Newtonsoft.Json
! 測試硬體:配置是E5-2670V2*2 測試用例:返回指定資料量的客戶列表資訊
獲取3個客戶資訊
JSON
G:\>bombardier.exe -c 100 -n 10000000 http://192.168.2.19:8080/customers_json/3 Bombarding http://192.168.2.19:8080/customers_json/3 with 10000000 request(s) us ing 100 connection(s) 10000000 / 10000000 [============================================] 100.00% 36s Done! Statistics Avg Stdev Max Reqs/sec 271738.73 67774.12 329181.89 Latency 361.86us 4.37ms 3.06s HTTP codes: 1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 244.72MB/s
Protobuf
G:\>bombardier.exe -c 100 -n 10000000 http://192.168.2.19:8080/customers_protobu f/3 Bombarding http://192.168.2.19:8080/customers_protobuf/3 with 10000000 request(s ) using 100 connection(s) 10000000 / 10000000 [============================================] 100.00% 41s Done! Statistics Avg Stdev Max Reqs/sec 243710.66 28345.63 275334.86 Latency 406.47us 829.25us 394.02ms HTTP codes: 1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 138.26MB/s
獲取10個客戶資訊
JSON
G:\>bombardier.exe -c 100 -n 10000000 http://192.168.2.19:8080/customers_json/10 Bombarding http://192.168.2.19:8080/customers_json/10 with 10000000 request(s) u sing 100 connection(s) 10000000 / 10000000 [============================================] 100.00% 51s Done! Statistics Avg Stdev Max Reqs/sec 196290.74 66381.50 263699.22 Latency 502.81us 4.00ms 3.05s HTTP codes: 1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 513.10MB/s
Protobuf
G:\>bombardier.exe -c 100 -n 10000000 http://192.168.2.19:8080/customers_protobu f/10 Bombarding http://192.168.2.19:8080/customers_protobuf/10 with 10000000 request( s) using 100 connection(s) 10000000 / 10000000 [==========================================] 100.00% 1m14s Done! Statistics Avg Stdev Max Reqs/sec 135254.64 24971.37 165490.90 Latency 737.06us 1.24ms 513.03ms HTTP codes: 1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 200.84MB/s
獲取20個客戶資訊
JSON
G:\>bombardier.exe -c 100 -n 10000000 http://192.168.2.19:8080/customers_json/20 Bombarding http://192.168.2.19:8080/customers_json/20 with 10000000 request(s) u sing 100 connection(s) 10000000 / 10000000 [============================================] 100.00% 54s Done! Statistics Avg Stdev Max Reqs/sec 182806.15 37623.75 209487.43 Latency 541.37us 1.48ms 0.90s HTTP codes: 1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 0.89GB/s
Protobuf
G:\>bombardier.exe -c 100 -n 10000000 http://192.168.2.19:8080/customers_protobu f/20 Bombarding http://192.168.2.19:8080/customers_protobuf/20 with 10000000 request( s) using 100 connection(s) 10000000 / 10000000 [==========================================] 100.00% 1m50s Done! Statistics Avg Stdev Max Reqs/sec 90249.67 9611.23 102294.37 Latency 1.10ms 1.04ms 518.03ms HTTP codes: 1xx - 0, 2xx - 10000000, 3xx - 0, 4xx - 0, 5xx - 0 others - 0 Throughput: 246.07MB/s
隨著返回的列表資料越大,Protobuf.net
的響應延時就越高,但伺服器的CPU資源佔用率比較低。而Newtonsoft.Json
雖然損耗了大量的CPU資源,但它能通過CPU資源可以有效地把併發數量提升起來;當在獲取20個客戶資訊的時候,基本把10Gb的頻寬佔滿並達到180000RPS。Protobuf.net
在CPU資源佔用率上來說雖然比'Newtonsoft.Json'要低很多,但面對一個悲劇的事情就是無法把RPS提升上去,在最後的測試結果裡落後了Newtonsoft.Json
一倍的RPS.
總結
隨著硬體資源大規模化,在測試程式的時候也要考慮這情況,程式無法在高配置資源完全發揮硬體資源的優勢這種情況針對我個人而言已經是第二次了,這種事情剛開始真讓人感覺到相當無助,因為這真的很難讓人接受的事實!其實出現這情況都是程式的某個功能點在多執行緒併發上出現了擁擠的情況,第一次出現這情況是.net core的ServerGC設定,而這一次看了Protobuf.Net的程式碼發現有些關鍵方法靜態方法上出現的多物件鎖的程式碼,可能是這些鎖導致在更多執行緒資源使用的時候無法達到一個更好的併發效果。最後在這裡提醒一下測試的朋友,程式的效能很重要,但有一點也很重要的就是完全發揮所有硬體資源處理更多的事情。
如果感興趣這個測試的程式碼,可以通過以下地址獲取:https://github.com/IKende/FastHttpApi/blob/master/WebApi_json_vs_protobuf.zip