Go vs Node vs Rust vs Swift
先前閱讀此文章覺得乏味就離開了,因為評測沒有太大的意義。
1. 為何我覺得原文的評比沒有意義?
因為效能評比的方式是 Fibonacci。
Fibonacci 比的不是 “數學計算” 也不是 “執行速度”,它只是多次小整數加法。再加上對編譯式語言或 Just-in-time 而言,多次的加法都能夠在一個 cycle 就處理完。
所以 Fibonacci 比較的其實是函式呼叫的開銷。其運算量與函式開銷的比率而言,離一般現實世界有點差距,所以評測結果也就沒有多大的參考依據。
但評比也不是完全沒有意義,如 c9s 所言,函式呼叫的開銷也可以是評比項目之一,只要不要把這個評比擴大解釋了。
2. Swift 適合 client side,而 Go 適合 server side?
兩者程式語言的初始想法似乎是如此,所以發展方向自然會傾向於各自專注的領域。
Go 與多數程式語言一樣,使用 Garbage collection (GC)。而 Swift 則是非 GC 的 ARC (Automatic reference counting),這與 Apple 的開發哲學有關,稍後再談。
GC 為人詬病的問題是,通常執行時無法保證會耗多久。我們知道 GC 運行時,會佔用一些系統資源,所以勢必影響其它的操作。例如,可能造成你玩遊戲時突然卡住。所以在一些需要順暢的應用中,如遊戲或影音,GC 問題會顯得很頭痛。
然 GC 的好處是,開發者不用顧慮記憶體回收,GC 通常會幫你處理得很好。記憶體終究會釋放,也沒有記憶體洩漏問題。
反之,ARC 的好處是,較能夠保證 Soft real-time response,讓你玩遊戲及影音時,比較不會出現卡住的情形。但壞處是,要顧慮記憶體回收,因此要求開發者必須有明確的設計與思路,否則容易造成記憶體洩漏或 Retain cycles 問題。
上述是一般情形,而現代 GC 除了採用並發外,也可以分批次處理,所以多數卡住的情形可以獲得解決,達到與 ARC 一樣的 Soft real-time response。況且很多程式語言,也提供可以避開 GC 的操作,例如 Java / Go 都有,彈性很大。
而 ARC 若要避免 Retain cycles,可以如 Python 採用的策略,平常使用 ARC,但仍會適時啟動 GC,以消除 Retain cycles。
所以依據前述分析,似乎也難說 Swift 適合 Client side 而 Go 適合 Server side?
其實還有一個很大的問題未提,Client side 通常是資源受限環境,例如手機。一般手機的記憶體量不如伺服器 (Server side) 那般。
GC 目前還有一項隱憂,就是需要比較多的記憶體運行才會有較佳的表現,這對資源受限的手機而言,是一大傷害。所幸,目前手機的記憶體量愈來愈高,讓這個問題獲得緩解。
但事實並非一定如此,當記憶體愈多時,GC 工作量也愈吃重,效能自然打折。這點對 ARC 也是一樣,只是 GC 比較明顯。
這也間接說明,為何 Android 手機通常比 iPhone 需要更多的記憶體,因為 Android 需執行類似 Java/JVM 的 GC。
為何說 “類似”?因為 Android 實際運行的 GC 並不是 Oracle Java/JVM,而是 Dalvik GC 或 ART GC。我們知道 Oracle Java/JVM 的 GC 非常成熟,但可惜因為智財權等問題,使得 Android 不能使用這般成熟的解決方案。
所以,Android 目前之所以通常比 iPhone 慢,有一個原因是 Android 上的 GC 並不是現行成熟的 GC。因此我們也很難說 ARC 是較 GC 更適用手機的方式。
3. Erlang GC
Erlang 使用的是 GC,但與 Go 全局 GC 不同。
Erlang 每個 Process 都有各自獨立的 GC,所以 GC 運行時,不像 Go 影響全局,而是影響該 Process。比 Go 擁有更成熟的 Soft real-time response。
所以 Erlang 較適合 real-time 應用,但因為 Erlang 不像 Go 是編譯式語言,所以運算效能不如 Go。例如 WhatsApp 使用 Erlang 很合理,畢竟訊息溝通需要 real-time 而不需大量運算。
4. Apple 的八卦
稍早有提到 Apple 的八卦。
Apple 早在 2012 年就決定從 OS X 中完全把 GC 去除了,他們相信 ARC 才是記憶體正確的管理方式。所以 Objective C 以及後來的 Swift 也自然都採用 ARC。