LavinMQ:理解程式碼以獲得最佳效能

使用 Crystal 開發 LavinMQ 是一個積極的選擇,因為保持對程式碼庫的控制是首要任務。十年的學習經驗讓快速更新和輕鬆修正錯誤成為優先考量。同時,選擇 Crystal 也提供了提升應用程式效能的機會。
LavinMQ 由 84codes 的資深開發人員建立,他們也是最大的雲端訊息傳遞平台之一 CloudAMQP 的創辦人。透過優先確保服務內部和服務之間的穩定通訊和可靠訊息傳遞,LavinMQ 的設計宗旨是在快速有效率地處理資料的同時,允許解耦的系統元件獨立運作並根據需要擴展。
LavinMQ 可以處理發布者、佇列和消費者之間的大量連線,這通常是物聯網 (IoT) 架構中的需求。它是一個開源訊息代理,經過預先最佳化,與其他代理相比速度極快,並且可以輕鬆處理每秒 100 萬條訊息。
LavinMQ 包含人們最想要的所有功能,並僅佔用少量記憶體空間,支援
- 串流
- 彈性路由
- AMQP 0.9.1 協定
- 確認和回執
- 串流佇列
- 無限佇列長度 (取決於磁碟空間)
- 複寫
我們強調了從技術角度來看突出的特性。它如何能夠每秒處理超過一百萬條訊息,並保持低記憶體佔用?一半的原因歸功於,我們引述
訊息寫入磁碟的速度非常快,快取由作業系統本身管理。這在保持低 RAM 佔用的同時,帶來了效能提升。
但另一半,正如在他們的部落格中所提到的,歸因於它是在 Crystal 中開發的。這體現在幾個有趣的方式上。
-
由於其 LLVM 後端,Crystal 可以有效率地編譯。這啟用了積極的最佳化,例如內聯方法和移除間接。
-
Crystal 協助開發人員將其資料配置在堆積或堆疊上。堆積配置成本很高,因此將資料配置在程式的熱路徑上的堆疊中會帶來重要的效能提升。Crystal 讓選擇資料的儲存位置變得容易。
-
Crystal 的 stdlib 和編譯器本身是用 Crystal 編寫的。Crystal 的黃金特性之一是其可讀性,使人們可以讀取程式將要執行的程式碼,而無需訴諸另一種通常是較低階的語言。
後者是本文的重點。事實上,標準函式庫的文件指向程式碼,明確指出呼叫特定方法的效能影響。例如,查看 Digest.file
的文件。點擊檢視原始碼,我們就會進入該方法的程式碼中。
能夠閱讀、理解甚至貢獻於語言及其 stdlib 的重要性在 84codes 為 Crystal 貢獻的其中一個 數個 PR 中得到了體現。細節並不重要,但如果您好奇,他們注意到在前面提到的 Digest
類別的方法中存在緩衝複製。以下摘錄顯示了該貢獻的主要部分;與新增的行和註解的差異,說明了為什麼在 io
物件中移除緩衝是有意義的。
diff --git a/src/digest/digest.cr b/src/digest/digest.cr
index e6a401e90545..bc38599da7f8 100644
--- a/src/digest/digest.cr
+++ b/src/digest/digest.cr
@@ -213,6 +213,7 @@ abstract class Digest
# Reads the file's content and updates the digest with it.
def file(file_name : Path | String) : self
File.open(file_name) do |io|
+ # `#update` works with big buffers so there's no need for additional read buffering in the file
+ io.read_buffering = false
self << io
end
end
一行小小的程式碼,卻可能對應用程式產生顯著的影響。對於應用程式和程式碼所依賴的函式庫使用相同的語言,對於理解程式碼的行為及其效能影響來說是一個巨大的優勢。
在結束之前,我們要指出 84codes 不僅為標準函式庫做出了許多改進:84codes 也是支持 Crystal 開發的主要贊助商。為了進一步突破該語言的極限,在撰寫本文時,他們正在大力支持改進 Crystal 程式的平行執行。或許下一版本的 LavinMQ 將在 Crystal 團隊的協助下,進一步突破極限!

Carl Hörberg,84codes 執行長
Crystal 在可讀性和效能之間取得了獨特的平衡。此外,我們能夠透過理解執行應用程式的底層程式碼來提升應用程式的效能。