簡體   English   中英

閑置的線程=壞?

[英]Threads sitting idle = bad?

我想在一小組機器上支持大約10,000個並發HTTP客戶端(盡可能小)。 我想在用戶使用應用程序時保持與每個客戶端的連接,以允許服務器推送更新。

我相信通常建議將async IO用於這些長期連接,以避免大量線程處於空閑狀態。 但線程閑置有什么問題? 我發現線程模型在精神上更容易使用,但我不想做一些會讓我頭疼的事情。 我想我將不得不進行實驗,但我想知道是否有人知道以前的這些實驗中的任何實驗?

異步I / O基本上意味着您的應用程序執行大部分線程調度。 而不是讓操作系統隨機掛起你的線程並安排另一個線程,你只有與CPU內核一樣多的線程,並在最合適的點上產生其他任務 - 當線程到達I / O操作時,這需要一些時間。

從性能的角度來看,上述似乎是一個明顯的勝利,但異步編程模型在以下幾個方面要復雜得多:

  1. 它不能表示為單個函數調用,因此工作流程不明顯,特別是考慮到由於異常而導致的控制流轉移時;
  2. 如果沒有特別針對編程語言的支持,成語非常混亂:意大利面條代碼和/或極弱的信噪比是常態;
  3. 主要是由於1.以上調試要困難得多,因為堆棧跟蹤並不代表整個工作單元的進度;
  4. 執行從池中的線程跳轉到線程(甚至是幾個池,每個抽象層都有自己的),因此使用常用工具進行分析和監視實際上是無用的。

另一方面,現代操作系統發生了許多有利的改進和優化,這大大消除了同步I / O編程的性能缺點:

  • 地址空間很大,所以為堆棧預留的空間不是問題;
  • 調用堆棧的實際物理RAM負載不是很大,因為只有線程實際使用的堆棧部分被提交到RAM,而調用堆棧通常不超過64K;
  • 對於較大的線程數而言過去非常昂貴的上下文切換已被改進到其開銷對於所有實際目的而言可忽略不計的程度。

經歷上述大部分內容和其他一些觀點的經典論文是我在這里所說的一個很好的補充:

https://www.usenix.org/legacy/events/hotos03/tech/full_papers/vonbehren/vonbehren_html/index.html

您的問題的評論中已經有一些很好的指示。

不使用10K線程的原因是這會花費內存資源,而內存會耗費能量。 編程模型沒有參數,因為坐在客戶端連接上的線程不能與想要發布事件的線程相同。

請查看Servlet 3.0標准中的websockets標准和異步請求處理模型。 所有最近的Java Web應用程序服務器現在都實現它(例如Glassfish和Tomcat),它是您的問題的解決方案。

由於您使用的操作系統,JVM和應用程序服務器缺失,因此無法回答問題本身。 但是,您可以通過使用Thread.sleep(9999999)創建一個servlet或JSP並在其上執行siege -c 10000 ...來快速測試它。

10,000個同時發生的HTTP客戶端......讓線程空閑的問題是什么?

似乎空閑線程的成本只是為內核結構(幾kb)和線程堆棧(512kb-一個mb的數量)分配的內存。 但...

顯然,你會不時地喚醒你的每一百個線程,對吧? 這是您支付上下文切換成本的時刻,這可能不是那么小(調用系統調度程序的時間,更多的緩存未命中等)。 例如,見: http//www.cs.rochester.edu/u/cli/research/switch.pdf

而且你必須非常小心地固定你的線程,以免影響系統線程。 因此,與異步IO相比,每次連接線程(在阻塞IO上)架構可能會增加系統的延遲。 但是,如果幾乎所有線程都停在大部分時間,它仍然適用於您的情況。

最后一句話。 我們不知道你的線程將在read()上被阻塞多少次,以及他們需要做多少工作來處理接收到的數據。 將使用哪些硬件,操作系統和網絡接口......因此,測試系統的原型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM