近日,亞馬遜官方博客上發布 “Sustainability with Rust” 一文,通過研究和對比來說明了 Rust 在可持續性方面優于其他語言。隨后,ZDNet 也對此文進行了報道。在 ZDNet 的報道發出之后,Go 技術負責人 Russ Cox連發 14 條推特,表示該文章在嚴重誤導大家對 Go 語言的認知。
這件事引起了大家的關注,同時也引發了“Rust 還是 Go”的大討論。那么,究竟發生了什么?
一篇文章引發的“對線”
在亞馬遜,Rust 已經成為大規模構建基礎設施的關鍵。2019 年,亞馬遜成為 Rust 項目的贊助商。2020 年開始招聘 Rust 維護者和貢獻者,并與谷歌、華為、微軟和 Mozilla 聯合成立了 Rust 基金會。
爭議 1:幾年前的研究有偏差
在發表的“Sustainability with Rust”文章中,為驗證 Rust 是一種節能的編程語言,使用了 2017 年的一項研究數據進行證明。這項研究主要是對 27 種編程語?進行 10 個基準問題測試,并測量執行時間、能耗和峰值內存使用情況。以下為文章中引起爭議的第一個部分:
幾年前有一項非常有趣的研究,主要探索能源消耗、性能和內存使用之間的關系。這是關于可持續發展的常見話題。我們對服務的能源或碳使用的了解很少,是否有代理指標?是否可以查看現有基礎設施成本、性能、內存等服務儀表板,并通過觀察到的趨勢來推測服務的能源消耗趨勢?
該研究在 27 種不同的編程語言中進行了 10 個基準測試,并測量了執行時間、能耗和峰值內存使用的情況。C 和 Rust 在能效方面明顯優于其他語言。事實上,它們的效率大約比 Java 高 50%,比 Python 高 98%。
C 和 Rust 比其他語言更高效就不足為奇了,但令人驚訝的是差異的幅度。保守估計,廣泛采用 C 和 Rust 可以將計算能耗降低 50%。
那為什么大家不更多地使用 C?它的語言和開發工具都非常成熟,社區規模也比 Rust 大得多。在 2021 年的開源峰會上,Linux 創造者 Linus Torvalds 坦言,用 C 語言實現代碼就像玩電鋸。作為一名終身寫 C 的程序員,Torvalds 知道,“(C 的微妙類型交互)并不總是合乎邏輯,對幾乎所有人來說都是陷阱。”
Torvalds 稱,Rust 是他見過的第一種可能解決問題的語言。Rust 提供了和 C 一樣的能效,同時還沒有未定義行為的風險。我們可以將能源消耗減半,同時不失去存儲安全的好處。
多項分析結果顯示,在 C/ C++中發生的高嚴重性 CVE 中,超過 70% 可以通過在 Rust 中實施相同的解決方案來預防。事實上,支持 Let's Encrypt 項目的非營利組織Internet Security Research Group (ISRG)(一個 2.6 億個網站的證書頒發機構),目標是將所有互聯網安全敏感的基礎設施都遷移到內存安全的語言上,目前進行的項目包括在 Linux 內核中支持 Rust ,以及將 curl 遷移到 TLS 和 HTTP 的 Rust 實現。
我們再看看其他的研究結果。上圖中間一列顯示了執行時間的測試結果,Rust 和 C 的執行時間非常相似,這兩種語言的執行速度都比其他語言要快。這意味著,選擇 Rust 可以在獲得可持續性和安全性優勢的同時,還將擁有 C 的優化性能。
那么,文章里的這段論述出現了什么問題呢?Cox指出,“幾年前的有趣研究”是明顯存在的問題。該研究于 2017 年 10 月在 Intel i5-4460 CPU(2014 年第二季度)上使用 Go 1.6(2016 年 2 月)進行。“那已經是永遠的過去式了。”最重要的是,這個“真正有趣的研究”假設計算機語言基準游戲是個可比較的程序來源,但了解這個網站的話就知道這完全不正確。
Cox表示,最明顯的是,如果研究聲稱 C++ 的能源消耗比 C 使用多 34% 、執行時間快 56% 和內存多 14% ,那就需要重新檢查這個研究的前提假設了。“幾乎每個 C 程序都是有效的 C++ 程序,所以 C++ 不會輸,尤其是沒那么糟糕!”
“所以,這個‘真正有趣的研究’并不是真正的有趣。事實上,我們應該以辯證的懷疑態度來看待。”Cox寫道。
爭議 2:不公平的對比
亞馬遜工程師在文章中還以聊天軟件 Discord 為例,講述從 Go 切換到 Rust 的過程。Cox認為,其引用的 Discord 內容里,關于從 Go 切換到 Rust 的部分存在令人難以置信的誤導。以下為文章中引起爭議的第二個部分:
Discord 最初以 Python、Go 和 Elixir 為主,但他們的一項關鍵 Go 服務存在問題。這是一個非常簡單的服務,但還是導致其尾部延遲嚴重。這是因為 Go 是一種垃圾回收 (GC) 語言,所以在創建和釋放對象時,垃圾回收器每隔一段時間就得停止程序的執行并運行一次垃圾回收。當 GC 運行時,進程無法響應請求,您可以看到 CPU 峰值和響應時間變化。
左:Go,右:Rust
為解決該問題,Discord 決定嘗試用 Rust 重寫服務,上圖顯示的就是使用結果。雖然 GC 峰值模式在 Rust 中消失了,但真正驚人的差異在于變化的幅度。注意, Go 和 Rust 的計量單位是不同的。
Rust 版本速度總體上快了 10 倍以上,甚至最差的尾部延遲減少了 100 倍。這些都是令人難以置信的改進,同時由于服務器響應效率變高,需要的服務器變少,這意味著使用的能源也更少。雖然 Discord 還沒有決定開始用 Rust 來減少能源消耗,但這就是影響。
另外,Rust 并不是第一種高效的語言。C 已經存在了很長時間,但 Rust 是第一個在不犧牲安全性的情況下保證高效率的主流編程語言。用 C 和 C++ 編寫的所有高危安全漏洞中,70% 是內存不安全造成的。Rust 提供了效率,但不會讓人覺得自己在玩火。
對此,Cox指出, Discord 的原帖中展示了一張 Go 服務器和等效 Rust 服務器的圖表。Rust 具有更可預測的性能,并避免了像 Go 中的延遲峰值,但它們的性能大致相當。
Discord 原帖中的對比圖,紫色線代表 Go,藍色線代表 Rust
相反,在亞馬遜的帖子里,在 Rust 和 Go 圖表標出了“ms”與“µs”的時間刻度對比。但該對比的前提是,Rust 服務器進行了重大重寫,并使用了新的數據結構和更多內存。
“這要么是完全沒有理解 Discord 的帖子,要么就是公然說謊。”Cox認為,這種對比方法在誠實、公平的情況下是很好的表達方式,“但 AWS 的帖子并非如此。”
不過,Cox指出 Discord 的帖子是公平的。“它將 Go 服務器和 Rust 服務器進行了對比,并在文章后面單獨繪制了 Rust 服務器在使用重寫的數據結構和額外內存后的變化圖,而 AWS 的帖子曲解了這一點。”
同時,Discord 的帖子也提到了 Go 1.10,而 Go 1.18 也將很快發布。這期間的 8 個版本有很多改進,減少了程序中有非常大的堆或非常多協議的 GC 暫停(Discord 服務器兩者都有)。因此,使用最近的 Go 版本將顯著減少 Discord 延遲峰值。“但 Rust 仍然是適合該服務器的優秀語言,團隊作出了合理的決定。”
Cox 沒有完全否認帖子里關于 Rust 的觀點,但在 Cox 看來,亞馬遜完全沒必要加上關于 Go 的誤導性陳述,“這看起來很丟人,Rust 足以獨立存在。”
Go、Rust 之爭
兩種語言起源于同一時期。Go 于 2007 年構思并在 2009 年 11 月公開,Rust 出現在幾個月后的 2010 年,盡管 Graydon 暗示 Rust 的構思可能要早得多。
Go 和 Rust 還有很多共同點。兩者都是現代軟件語言,旨在為影響軟件開發的問題提供安全且可擴展的解決方案。兩者還都是針對當時現有語言遇到的問題而創建,特別是開發人員在生產力、可擴展性、安全性和并發性方面遇到的問題。因此,兩者常被認為是競爭關系。
但兩者也有很多差異。谷歌 Go 編程語言的產品和戰略負責人 Steve Francia 認為,Go 和 Rust 在性能并發、可擴展性、開源意識等方面有著相似之處,但兩者有不同的權衡。Francia 在發布到thenewstack的文章里,詳細比較了 Go 和 Rust 的差異。
在性能方面,Go 具有開箱即用的出色性能。按照設計,Go 中沒有可以榨取更多性能的按鈕或操縱桿。Rust 旨在讓開發者能夠從代碼中榨取出每個性能,因此 Rust 有著更快的速度,代價是增加了復雜性。
在適應性方面,Go 快速迭代的優勢使開發人員能夠快速嘗試想法,并在解決手頭任務的工作代碼上進行磨練。這通常就已經足夠了,開發人員可以騰出時間做其他任務。另一方面,與 Go 相比,Rust 的編譯時間更長,導致迭代時間更慢。這使得在更短周轉期內,Go 允許開發人員能在不斷變化的需求場景中工作得更好,Rust 則可以在擁有更多時間進行更精細、更高效開發的實現場景中發揮出色。
在易學性方面, Go 是更平易近人的語言,很多團隊甚至能夠在幾周內使用 Go 并將 Go 服務/應用程序投入生產。而由于其復雜性,Rust 被認為是一種難以學習的語言,但這也為 Rust 帶來了更高的性能。
在精確控制方面,Rust 擁有很大的優勢。Rust 可以使開發人員在如何管理內存、如何使用機器的可用資源、如何優化代碼以及如何制定解決方案等問題上,有更精準地控制。
因此,Francia 給出的建議是,Go 是大多數公司和開發者的正確默認選項,因為 Go 性能強大、易于采用,高度模塊化特性使其特別適用于需求不斷變化的情況。隨著產品成熟和需求趨于穩定,企業可能有機會從邊際性能的提升中獲得巨大的收益。這些情況下,采用 Rust 來使性能最大化可能會是不錯的選擇。