2013-02-25 177 views
11

我正在實現需要維護非常大數量(100K或更多)長連接的自定義服務器。服務器只是在套接字之間傳遞消息,並沒有做任何嚴肅的數據處理。消息很小,但其中許多消息每秒都會收到/發送。減少延遲是目標之一。我意識到使用多核並不會提高性能,因此我決定通過調用run_onepoll方法io_service對象在單線程中運行服務器。無論如何,多線程服務器將更難實施。Boost Asio單線程性能

什麼是可能的瓶頸?系統調用,帶寬,完成隊列/事件解複用?我懷疑調度處理程序可能需要鎖定(這是由asio庫內部完成的)。是否可以禁用boost.asio中的隊列鎖定(或任何其他鎖定)?

編輯:相關的問題。多線程可以提高系統調用性能嗎?我的感覺是,因爲系統調用是內核原子/同步的,添加更多的線程不會提高速度。

+0

如果您在一個線程中運行所有內容,則不需要任何(手寫)鎖。 – 2013-02-25 18:29:23

+1

使用多核可能會提高性能 - 請參閱http://cmeerw.org/blog/748.html#748和http://cmeerw.org/blog/746.html#746,瞭解去年所做的一些基準測試。 – cmeerw 2013-02-25 19:58:30

回答

15

您可能想要閱讀幾年前的my question,當我在開發系統軟件Blue Gene/Q supercomputer時首次調查Boost.Asio的可伸縮性時詢問了它。

擴展到100k或更多的連接應該不成問題,但您需要了解明顯的資源限制,例如打開的文件描述符的最大數量。如果您還沒有閱讀精華版C10K paper,我建議您閱讀它。

您已經實現了使用單線程和單一io_service您的申請後,我建議研究線程調用io_service::run()池,然後才調查釘扎的io_service到一個特定的線程和/或CPU。在所有這三種設計的Asio文檔中都包含了多個示例,並且在SO上有several questions以及更多信息。請注意,當您引入多個調用io_service::run()的線程時,您可能需要實現strand,以確保處理程序可以獨佔訪問共享數據結構。

9

使用boost :: asio,你可以編寫大約相同開發成本的單線程或多線程服務器。您可以編寫單線程版本作爲第一版本,然後將其轉換爲多線程(如果需要)。

通常,只有boost :: asio的瓶頸是epoll/kqueue反應器在互斥體中工作。所以,只有一個線程在同一時間做epoll。這可能會降低性能,因爲當您有多線程服務器時,服務器會提供很多很多很小的數據包。但是,無論如何,它應該比簡單的單線程服務器更快。

現在談談你的任務。如果你只想在連接之間傳遞消息 - 我認爲它必須是多線程服務器。問題是系統調用(recv/send等)。一條指令對CPU來說很容易,但任何系統調用都不是非常「輕鬆」的操作(一切都是相對的,但相對於任務中的其他作業)。所以,單線程你會得到很大的系統調用開銷,爲什麼我建議使用多線程方案。

此外,您可以單獨使用io_service並使其成爲「每線程io_service」成語。我認爲這必須提供最好的性能,但它有缺點:如果io_service中的一個會得到太大的隊列 - 其他線程無法幫助它,所以一些連接可能會減慢。另一方面,單個io_service - 隊列溢出會導致大的鎖定開銷。你所能做的就是 - 做兩種變體並測量帶寬/延遲。實現這兩種變體應該不是太困難。