2013-10-31 75 views
0

我有一個控制檯應用程序(C#),我必須調用各種第三方API並收集數據。這我必須同時爲不同的用戶做。我正在使用線程。但隨着用戶數量的不斷增加,這項服務正在蠶食CPU的性能。它正在影響其他進程。有沒有一種方法可以使用線程進行並行處理,但不會以巨大的方式影響CPU的性能。線程進入CPU性能

+1

線程不是輕量級的。如果它正在等待網絡響應,則可以使用IO完成端口,它們重量較輕並且不受特定線程限制。或者你可以避免直接使用線程,而是使用類似TPL的東西。我喜歡簡單地使用TPL。 –

+1

當有更多的用戶或忙於管理線程時,你的CPU是否忙於做更多的工作?如果你相信它是後者,你爲什麼這麼想? –

+0

除了@AdamHouldsworth提到的一點,你能給我們一個特定數量的用戶嗎?我們是否正在討論從1個用戶峯值轉換爲10個用戶,還是1000個用戶峯值轉換爲100.000個用戶? – Stefan

回答

0

首先,運行一個profiler並簽出一些refactoring工具以查看是否可以執行代碼優化來解決問題。如果您的應用程序仍然超載服務器,請設置或購買load balancing。與此同時,如果你正在運行最新的操作系統,你可以嘗試設置一個hacky CPU rate limit ......但是,這可能不適合你描述的需求。

1

我從你的問題中假設你正在手動創建線程,所以回答這個問題的快速方法是建議你使用一個類似於Task Parallel Library的API,因爲這將需要任意數量的任務並嘗試使用一個合理的線程數來處理它們 - 所以如果給定500個API請求,它會將自己限制在幾個線程中。

但是,要更詳細地回答:您會看到此問題的典型原因是代碼創建的線程過多。線程不是免費資源 - 它們很貴。

一個由例如根據您的問題可能是這樣的:

  • 您有需要調用5層第三方的API,每個將要每用戶
  • 返回數據的〜1MB
  • 調用在一個單獨的後臺線程每個API,對於每個用戶
  • 有100個用戶
  • 你因此已在總500個創建線程,其中的每一個上的數據等待從網絡

這裏的問題是程序試圖管理500個線程,他們都在等待最慢的系統 - 網絡。

更簡單地說,我們正在嘗試一次下載500個數據(在這個例子就意味着一切結束慢),而不是下載它們一次一個使個別項目將提前結束。由於每個線程都將無所事事(只是等待網絡),CPU將不斷地在空閒線程之間切換。隨着用戶數量的增加,線程數量增加 - 這會增加CPU使用量,僅僅是爲了在線程之間切換,即使每個線程實際上下載速度更慢。這是(大約)爲什麼隨着用戶數量的增加,您會看到性能降低的原因。

一個更好的例子將採取同樣的場景,只使用一個後臺線程:

  • 您有需要調用5層第三方的API,每個將要返回〜1MB的每用戶數據
  • 每個API調用被放入一個隊列,該隊列處理由單個線程
  • 有100個用戶
  • 你因此具有1個線程,其中使用全部可用bandw後臺運行每個請求的網絡寬度

在本示例中,您的CPU使用率將非常一致 - 無論您擁有多少用戶,只有一個後臺線程正在運行,因此上下文切換會最小化。每個單獨的API調用都以網卡的最大速率運行,因此會盡快結束。

現實情況是,一個線程可能不夠:單個請求不太可能使網絡飽和,因爲其他地方會有限制因素。但是你可以稍後調整:可能有2或3個線程會更高性能,但是4個線程會再次變慢。線程的一般規則是從開始很小並且工作起來,而不是爲每件作品創建一個線程。

+0

'CPU將在不斷的空閒線程之間切換' - 一個有點誤導性的聲明:) –

+0

沒錯,那是一個糟糕的選擇。不過,你會看到更多的上下文切換,而不是有用的。 –

+0

我無法將它們保留在隊列中,只處理單個線程。這樣一個完整的迭代將花費大量時間完成。假設我使用其API爲100個用戶綁定Twitter時間線。第100位用戶必須等待99個線程才能完成時間線更新。如果我可以同時處理它們,那麼在獲取和顯示他的時間表方面就不會有那麼遲。 –