為何Symless選擇Rust,而不是Go、C++或Node.js?

banq發表於2022-02-24

我們決定為 Synergy 3 後臺服務(目前用 Node.js 編寫)使用Rust(不是 Go 或 C++),因為我們相信它會給我們的客戶帶來更好的體驗。沒有考慮 Java。

我們選擇 Rust 並不是因為它是Stack Overflow 連續四年最受歡迎的語言,儘管大多數跳到 Rust 的人已經愛上了並留下了。我們選擇 Rust 主要是因為它的記憶體安全優勢。順便說一句,Rust 比其他語言更環保,而且 Rust 社群最歡迎跨性別者(考慮我們的招聘策略)。

 

Synergy 3 由三個部分組成:

  • C++ 核心(執行實際的滑鼠和鍵盤共享),
  • Electron GUI(用於配置,用 JavaScript 編寫,帶有 React),
  • 以及Node.js 服務(一個臨時原型,用 TypeScript 編寫)。

該服務提供自動發現(通過 mDNS),使所有計算機之間的配置保持同步,並將在未來提供其他功能,例如所有計算機的一鍵式自動更新。

 

在決定需要用比 Node.js 更好的效能來編寫服務後,我們最終決定將 Rust 和 Go 作為可能的選項(根據我們從 Synergy 2 中獲得的經驗,早期不包括 C++)。

團隊花了一些時間在 Rust 和 Go 中開發了一些小型演示專案,以瞭解這些語言。Rust 和 Go 是非常不同的語言,因此很難比較。儘管如此,我們還是與開發團隊開會,並提出了一個電子表格矩陣。

為何Symless選擇Rust,而不是Go、C++或Node.js?

以下是我們在決策表中的含義的一些定義。很多評分都是非常主觀的、特定於團隊的和特定於專案的。因此,這些數字可能對其他專案或與其他團隊的決策沒有用處,但它應該讓您瞭解我們是如何為 Synergy 做出決策的。

  • 穩定性:Synergy 3服務的穩定性如何(即記憶體安全,等等)。
  • 開發時間:在我們有的時間內,我們能夠做出多少開發過程。
  • 培訓/採用:該語言對各種開發人員來說有多容易掌握。
  • 招聘--成本:企業要花多少錢(招聘廣告、管理、面試等)。

    招聘--受歡迎程度:有多少開發者真正想使用這種語言。

    招聘--可用性:有多少人在尋找該語言的角色。

  • 庫:是否有我們需要的庫,它們是什麼樣子的?
  • 社群:社群有多強大,多平易近人,多有幫助?
  • 語言特點:語言功能是否能很好地滿足我們的需要?

 

記憶體安全是首要決定因素

我們發現,記憶體錯誤是我們最大的擔憂,因為Synergy 3服務是一個長期執行的過程。我們還考慮到,在2019年,微軟揭露了他們70%的bug都與記憶體安全有關。

對於記憶體安全,我們有幾個選擇。用Node.js和Go編寫的程式碼可以通過足夠的工作來實現記憶體安全,但它們都是基於GC的,這不可避免地導致工程師容易忽略記憶體安全問題,不自覺地依賴語言執行時來清理它們。另一方面,C++沒有GC,所以你必須對記憶體管理進行更嚴格的管理,但語言本身並不能保護你。你不能把記憶體洩漏的原因歸咎於C++,只能怪你自己。例如,打破封裝或將C語言的指標運算與C++混合在一起,就會出現記憶體錯誤......但這很容易做到,特別是對於經驗不足的開發者。unique_ptr怎麼樣?當然可以,但你不一定要用它。

 

另一方面,Rust根本不允許你對記憶體不安全(當然,除非你故意洩露記憶體)。這是一把雙刃劍,因為有兩個原因。

它使學習語言變得更加困難;借用和所有權的概念需要花時間來學習。例如,如果你用同一個變數呼叫一個函式兩次,Rust會很不留情面,因為你會得到一個編譯器錯誤。C++、Go和Node.js會讓你做這樣的事情,而沒有任何直接或明顯的後果。

在Rust中,你不得不考慮記憶體分配和記憶體管理。是的,也許在某種程度上,C++也會讓你思考這些事情,但不是通過直接的編譯器錯誤......相反,在C++中,你經常在執行時學習這些。微軟安全工程師馬特-米勒(Matt Miller)因談到過去十年中微軟的大部分補丁都是對記憶體安全漏洞的修復而聞名,這可能是Hyper-V團隊考慮使用Rust的一個因素。

 

為什麼不堅持使用Node.js?

Synergy 2服務(在那裡犯了錯誤)純粹是用C++編寫的,所以最初我們在選擇1)用C++重寫Synergy 3 Node.js服務,和選擇2)堅持用Node.js來做服務。

Node.js在突破和快速編寫程式碼方面非常出色,所以它在原型階段非常好。如果用Rust、Go或C++,那就有點麻煩了,因為它變化太大,而且我們也不完全確定我們編寫的程式碼是否是適合我們客戶的解決方案。但是,我們對現在的情況相當肯定,所以整個開發團隊覺得是時候把程式碼移植到使用記憶體和CPU較少的地方了。

Synergy 3服務的後臺程式將在使用者的桌面上連續執行數月,在後檯安靜地工作。所以,記憶體錯誤導致了可怕的使用者體驗(如果使用者不是很有技術含量,他們不知道為什麼他們的電腦變成了一個滯後的爛攤子)。實際上,我們在Synergy 2的C++服務中看到了類似的記憶體安全問題,所以這是一個我們經歷過的真實問題。

對於我們的產品,使用Rust而不是Node.js會帶來更好的使用者體驗。 

 

但你不能真的將Go與Rust進行比較

我與我最信任的CTO聯絡人中的大約20人進行了交談。為了保持客觀,每次談話都以這樣的方式開始。"知道Rust或Go嗎?"

以下是其中一次談話。他的回答。

"[Go]說到底只是另一種類似C的語言。 Rust則完全是另一種野獸。根據我所接觸的其他人的傳聞,大多數人都喜歡它的想法,但發現它非常難以操作。 如果你問我,我想它會因為這個原因而曇花一現,但誰也說不準。"

我問他,他是否認為Rust可能會曇花一現,因為它比Go更難操作。

他回答說

"嗯,也許只是一般的難,而不是明確地與Go相比。 在我看來,它們的目標市場是完全不同的。我認為Rust應該是C++的現代替代品--即非常接近裸機的東西;而Go我認為是針對更高層次的應用。 因此,我認為這實際上是Rust與C++的對比,而不是Rust與Go的對比"。

 

Discord Gophers伺服器上的Go開發者傾向於同意這個觀點;Rust並不具有真正的可比性,因為它的目的完全不同。

有趣的是,Rust似乎有一個難以操作學習的名聲。很可能是因為借貸檢查器和所有權的概念,它執行了記憶體安全。但是,現有的Rust開發者當然有不同的看法。

  • "我發現Rust遠比C++容易操作。"
  • "特別是借貸檢查器可能是一種痛苦,但總體而言,它要容易得多。"
  • "Rust用短期的易用性換取長期的健壯性。"

來源。Rust Discord伺服器

 

我的另一位CTO聯絡人對Rust與Go有一個有趣的觀點。關於在二者之間做出選擇的問題

"肯定是Rust,特別是如果你對運送一個能正常工作的二進位制檔案感興趣的話。Rust對於接近C++型別的工作來說是一個非常好的開發經驗。因此,也許比Node.js對開發不那麼友好,但你可以讓你的DevOps流程幾乎相同。另外,你可以傳送一個WASM,這可能會給你一些創造性的機會,比如Chromebooks。

我對Go的體驗很好,但實際上是為了將微服務運送到我控制的環境中。我對語言本身只有輕微的興趣--感覺它在向正確的方向嗅探,但我有點覺得Rust是通過研究C++、C#、Node.js、Python和Golang來獲得靈感的,並從語言、編譯、目標、生態系統、社群等方面汲取了大部分的精華。"

 

一些程式設計師的幽默

"Rust背後的最初目的是讓人們有能力自鳴得意地談論C和C++有多麼不安全,但最近它被重新利用為一種可行的系統級語言"

 

"Rust是一門語言,你試圖說服編譯器你的程式碼是正確的,最終大部分時間都會失敗"

許多剛接觸Rust的開發者一開始往往會在所有權上掙扎,這是Rust的突破性功能,它消除了對GC的需求;掌握了所有權,Rust將是你在記憶體安全方面最好的朋友。如果你忽略了所有權,你就會不斷地與編譯器鬥爭。

此外,還有借貸檢查器,它做了很多事情來確保記憶體安全,比如確保所有變數在使用前都被初始化。它還強制要求你不能兩次移動同一個值,而且你不能在借用時移動一個值。

 

"Rust是一種為Rust開發者製造的程式語言"。

編譯器的獨特性確實使其有別於任何其他語言,而且學習曲線最初是相當陡峭的。因此,當你開始學習Rust時,可能會很艱難,但一旦你掌握了基礎知識,真正靠攏了概念,這門語言就會變得很容易使用。

相關文章