[英]Timing a remote call in a multithreaded java program
我正在編寫一個壓力測試,它將向遠程服務器發出許多呼叫。 我想在測試后收集以下統計信息:
我可以成功獲得(2),但是我遇到了(1)問題。 我當前的實現與另一個SO問題中顯示的實現非常相似。 我在那個問題中描述了同樣的問題:使用System.currentTimeMillis()
報告的延遲時間比使用多個線程運行測試時的預期時間要長。
我分析了問題,並確定問題出在線程交織上(請參閱我對上面鏈接的另一個問題的回答以獲取詳細信息),並且System.currentTimeMillis()
不是解決此問題的方法。
看來我應該能夠使用java.lang.management
做到這一點,它具有一些有趣的方法,例如:
ThreadMXBean.getCurrentThreadCpuTime()
ThreadMXBean.getCurrentThreadUserTime()
ThreadInfo.getWaitedTime()
ThreadInfo.getBlockedTime()
我的問題是,即使我已經閱讀了API,但仍不清楚這些方法中的哪一種可以滿足我的需求。 在我鏈接的另一個SO問題的上下文中,這是我需要的:
long start_time = **rightMethodToCall()**;
result = restTemplate.getForObject("Some URL",String.class);
long difference = (**rightMethodToCall()** - start_time);
這樣,即使在多線程環境中,該difference
使我可以很好地近似到遠程調用所花費的時間。
限制:我想避免使用synchronized
塊來保護該代碼塊,因為我的程序還有其他線程希望繼續執行。
編輯:提供更多信息。
問題是這樣的:我想為遠程呼叫計時,而只是為遠程呼叫計時。 如果我使用System.currentTimeMillis
或System.nanoTime()
,並且如果我的線程多於內核,那么我有可能使該線程交錯:
如果發生這種情況,則Thread2計算出的差是正確的,但Thread1計算出的差是不正確的(它將大於應有的差)。 換句話說,為了測量Thread1中的差異,我想排除第4行和第5行的時間。這是否該線程正在等待?
以不同的方式總結問題,以防其他人更好地理解它(這是@ jason-c在他的評論中的說法):
[我正在嘗試為遠程調用計時,但是使用多個線程運行測試只是為了增加測試量。
使用System.nanoTime()
(但請參見此答案末尾的更新)。
您絕對不希望使用當前線程的CPU或用戶時間,因為用戶感知的延遲是掛鍾時間,而不是線程CPU時間。 您也不想使用當前線程的阻塞或等待時間,因為它會測量每個線程的爭用時間,而這也不能准確地表示您要測量的內容。
System.nanoTime()
將返回相對准確的結果(盡管從技術上講,粒度僅保證與currentTimeMillis()
或更好currentTimeMillis()
,但實際上,粒度往往要好得多,通常使用硬件時鍾或其他性能計時器來實現,例如QueryPerformanceCounter
on Windows或Linux上的clock_gettime
),並使用具有固定參考點的高分辨率時鍾,將准確測量您要測量的內容。
long start_time = System.nanoTime();
result = restTemplate.getForObject("Some URL",String.class);
long difference = (System.nanoTime() - start_time);
long milliseconds = difference / 1000000;
System.nanoTime()
確實有其自身的問題,但請注意不要被妄想症所困擾 。 對於大多數應用來說,這已經足夠了。 例如,當您將音頻樣本發送到硬件或其他東西時,您只是不想使用它來精確計時(無論如何您都不會直接在Java中這樣做)。
更新1:
更重要的是,您如何知道測量值比預期更長? 如果您的測量顯示了真實的時鍾時間,並且某些線程所花費的時間比其他線程長,那么這仍然是用戶感知的延遲的准確表示 ,因為某些用戶將經歷更長的延遲時間。
更新2(基於注釋的澄清):
我上面的大部分答案仍然有效。 但是出於不同的原因。
使用每個線程的時間並不能給您准確的表述,因為在遠程請求仍在處理時,線程可能處於空閑/不活動狀態,因此,即使是感知到的延遲的一部分,您也可以從測量中排除該時間。
遠程服務器引入了更多的不准確性,需要花費更長的時間來處理您同時發出的請求-這是您要添加的一個額外變量(盡管可以接受,代表遠程服務器正忙)。
掛牆時間也不是完全准確的,因為如您所見,本地線程開銷的變化可能會增加額外的延遲,這在單請求客戶端應用程序中通常不存在(盡管這可以接受作為代表客戶端應用程序的代表)多線程,但這是您無法控制的變量)。
在這兩個時間中,壁掛時間仍然比每個線程的時間更接近實際結果,這就是為什么我在上面留下了前面的答案。 您有幾種選擇:
另外,這些都不能保證系統上其他不相關的線程不會影響您的計時,所以這就是為什么a)多次運行測試並進行平均(顯然)和b)設置可接受的值很重要的原因對時序誤差的要求是您可以接受的(您真的需要知道例如0.1ms的精度嗎?)。
就個人而言,我要么做第一個單線程方法,讓它運行一整夜或一個周末,要么使用您現有的方法,從結果中去除異常值,並接受時間上的誤差。 您的目標是在令人滿意的誤差范圍內找到現實的估計 。 在確定可接受的內容時,您還需要考慮最終將使用此信息做什么。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.