[英]CPU costs of Thread.sleep() and Thread.onSpinWait()
[英]CPU usage is 100% during Thread.onSpinWait()
我正在為我的加密交易機器人編寫回測原始數據收集器,但遇到了一個奇怪的優化問題。
我經常在 Executors.newCachedThreadPool() 中有 30 個可運行對象,運行來自 API 的獲取請求。 由於 API 的請求限制為每分鍾 1200 個,因此我的可運行文件中有以下代碼:
while (minuteRequests.get() >= 1170) {
Thread.onSpinWait();
}
是的,minuteRequests 是一個 AtomicInteger,所以我沒有遇到任何問題。
一切正常,問題是即使我使用推薦的忙等待 onSpinWait 方法,當啟動等待時,我的 CPU 使用率從 24% 左右上升到 100%。 作為參考,我在 3900X(24 線程)上運行它。
關於如何更好地處理這種情況的任何建議?
我的建議是不要忙着等待。
Thread.onSpinWait
的javadocs是這樣說的:
表示調用者暫時無法繼續,直到其他活動發生一個或多個動作。 通過在自旋等待循環構造的每次迭代中調用此方法,調用線程向運行時指示它正忙於等待。 運行時可能會采取措施來提高調用自旋等待循環構造的性能。
請注意,突出顯示的部分使用了單詞may而不是will 。 這意味着它也可能不會做任何事情。 此外,“提高性能”並不意味着您的代碼會客觀有效。
javadoc 還暗示改進可能取決於硬件。
簡而言之,這是使用onSpinwait
的正確方法……但是您對它的期望太高了。 它不會使您的忙等待代碼高效。
那么我會建議你實際做什么呢?
我建議您將AtomicInteger
替換為Semaphore
( javadoc )。 此特定循環將替換為以下內容:
semaphore.acquire();
這會阻止1直到 1 個“許可”可用並獲取它。 有關信號量如何工作的說明,請參閱 class javadocs。
注意:由於您沒有向我們展示您的速率限制的完整實現,因此不清楚您當前的方法實際上是如何工作的。 因此,我無法准確告訴您如何將AtomicInteger
替換為Semaphore
。
1 - 被阻塞的線程被“停放”,直到其他線程釋放許可。 當它被停放時,線程不運行並且不與 CPU 內核相關聯。 內核要么處於空閑狀態(通常處於低功耗狀態),要么被分配給其他線程。 這通常由操作系統的線程調度程序處理。 當另一個線程釋放許可時, Semaphore.release
方法將告訴操作系統解除在acquire
中阻塞的線程之一。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.