整理 | 蘇宓
出品 | CSDN(ID:CSDNnews)
近日,來自多倫多大學和 YScope 公司(為軟件系統提供創新的日志管理和故障排除工具。由一群計算機工程教授和博士創立)的 David Lion、多倫多大學 Adrian Chiu 和 Michael Stumm、多倫多大學和 YScope 公司 Ding Yuan 共同發布了一份《調查托管語言的運行時性能:為什麼 JavaScript 和 Python 比 C++ 慢了 8 倍和 29 倍,而 Java 和 Go 卻能更快》(https://www.usenix.org/system/files/atc22-lion.pdf)的論文分析報告,深度剖析了不同編程語言運行時在代碼開發中真實的性能情況,由此方便開發者可以精確地測量執行任何字節碼指令所花費的時間等。
性能是系統軟件不得不面對的挑戰
在報告中,研究人員指出,自 2015 年以來,具有集成運行時環境的編程語言越來越受歡迎,其中,全球知名的代碼托管平台 GitHub 上最受歡迎的三種語言分別是 JavaScript、Java 和 Python。
作為開發利器,編程語言幫助開發者快速構建各種應用程序和服務,也極大地提高了生產力。同時,這些語言自身也提供了各種功能,如動態類型檢查、帶有垃圾收集的內存管理,以及動態內存安全檢查等等。為此,研究人員用「托管語言」(managed languages)專業術語來指代這些類型的編程語言。
現實來看,托管語言越來越多地被用於實現性能至關重要的系統軟件上,如Hadoop 和 Spark 都在 Java 虛擬機(JVM)上運行,因為它們分別用 Java 和 Scala 實現;Kubernetes、etcd(分布式鍵值存儲)和 M3(由 Uber 建立的分布式時間序列數據庫和查詢引擎)都是用 Go 實現的。
當前,甚至連操作系統(OS)的內核 Biscuit 也是用 Go 實現的 。Openstack、Paypal、Instagram 和 Dropbox 都大量使用 Python,其中,Python 是 Dropbox "在後台服務和桌面客戶端應用中使用最廣泛的語言",在一個存儲庫中就有近 400 萬行 Python 代碼;JavaScript 也被用於 Facebook 的 Bladerunner pub/sub 系統的性能關鍵路徑中。
在開發過程中,編程語言的性能在一開始很少會被考慮到項目中,部分原因是不少開發者認為性能問題可以在以後慢慢去解決,也許可以通過簡單地增加硬件來進行橫向擴展。
不過,隨著代碼產品或服務使用規模的擴大,服務變得越來越慢或者硬件成本變高,性能成為一個不容忽視的問題。這也是為什麼 Stream 要放棄了 Python 而改用 Go、 Discord 從 Go 切換到 Rust、Twitter 從 Ruby on Rails 切換到 Scala 和 Java 的主要原因。
不少開發者往往為了提升性能,想破腦袋,但現實只有兩條路,一條是從現有的代碼中想盡辦法盡可能地做優化,另一條是思考使用的編程語言是否已經達到了性能極限,看看有沒有必要將舊的代碼移植到一個新的性能更高的語言上。
為了徹底解開系統軟件中不同編程語言導致的性能問題,研究人員決定以 C++ 為極限,對 Java、Go、JavaScript 和 Python 四種編程,還有應用最廣泛的運行時系統 CPython、OpenJDK。Node.js 與 JavaScript 的 V8 引擎進行深入的定量性能分析。
同時,研究人員還從頭開始建立了 6 個應用程序,並創建了一個名為 LangBench 基准(https://github.com/topics/langbench)。這些應用程序涵蓋了各種不同的計算強度、內存使用、網絡和磁盤 I/O 強度以及可用的並發性的應用場景等復雜性。對此,研究人員全面分析了它們的完成時間、資源使用和可擴展性。
測試方法
值得一提的是,研究人員指出,這份論文沒有也不可能全面地回答與語言運行時的性能有關的每一個問題。本文只是評估了四種語言的運行時,而且對於每種語言,只評估了最廣泛使用的實現。此外,研究人員只在一個單一的操作系統/硬件堆棧上運行了工作負載。其研究結果與使用的基准有關,這些基准模擬了現實生活中的應用,但可能不代表廣泛的應用。
在測試方法上,研究人員在兩台內部服務器上進行了實驗,每台服務器有 2 個Xeon E5-2630V3、16 個虛擬核心、2.4GHz CPU、256GB DDR4 內存和兩個 7200 RPM 硬盤。它們運行的系統是 Linux 4.15.0,並通過 10Gbps 的互聯網絡連接。
對於 C++ 程序,研究人員使用的是 GCC 9.3.0 根據 C++17 標准用 -O3 進行編譯。對於 OpenJDK 13、CPython 3.8.1 和Go 1.14.1 ,其使用了各自語言的參考實現。同時,使用 Node.js 13.12.0 和 V8 7.9.317.25 版本。
研究人員對每個基准進行了 5 次測試,取平均值。其中,在運行鍵-值存儲、日志分析器和文件服務器的基准時,client 和 worker 線程的數量從 1 到 1024 不等。對於 OpenJDK 和 V8 來說,最小的內存量是通過確定不會導致崩潰的第一個堆配置來設置的;對於 Go 來說,GOGC 被設置為5%。然後研究人員不斷增加堆的設置,直到性能不再提高。其使用第一個設置的結果(即最小的堆大小)得出最佳性能。對於日志解析器和文件服務器基准,所用的日志文件被存儲在一個復制系數為 2 的分布式文件系統上。 在運行每個基准之前,研究人員都清除了 Linux 的頁面緩存,以保證測試准確性。
Java、Go 更具競爭力,JavaScript、Python 比 C++慢了 8 倍和 29 倍
最終 LangBench 中各項基准的運行時間結果如下所示:
其中,優化的 GCC 平均速度最快,Go 和 OpenJDK 緊隨其後,比 GCC 慢了 1.30 倍和 1.43 倍。令人印象深刻的是,在 12 項基准測試中,Go 和 OpenJDK 有 3 項超過了優化的 GCC。
總體而言,研究人員發現 V8 / Node.js 和 CPython 表現最差,執行應用程序的平均速度分別比 C++ 應用程序慢 8.01 倍和 29.50 倍,這意味著運行時下,JavaScript、Python 要比 C++ 慢這麼多。更糟糕的是,這兩個運行時上的應用程序擴展性很差,因為它們無法有效地利用多個內核。在極端情況下,CPython 比 GCC 慢了 129.66 倍(在排序基准中)。V8/Node.js 和 CPython 只有在工作負載受到磁盤 I/O 的瓶頸時,即在文件服務器基准中,才與 GCC 有競爭力。
相比之下,OpenJDK 和 Go 應用程序即 Java 和 Go 語言比 C++ 更具有性能競爭力,運行速度僅慢了 1.43 倍和 1.30 倍,並且可以輕松擴展到多個內核。在一些應用中,OpenJDK 和 Go 的性能超過了 C++ 的同類產品。
更多完整報告內容詳見:https://www.usenix.org/system/files/atc22-lion.pdf
— 推薦閱讀 —
*眼睛小被誤判“開車睡覺”?網友:這波不怪小鵬,真的
*損失37億!Intel將徹底退出傲騰存儲業務;支付寶新增一鍵取消「自動扣款」功能;iOS 15.5驗證通道關閉|極客頭條
*在 M1/M2 Mac 上,讓 Windows 11 免費“跑”起來!
《新程序員001-004》已全面上市
掃描下方二維碼或點擊進入立即訂閱