摘要:作者唐劉很早之前就看過大神的一篇文章,里面提到了性能測試工具的問題,但當時并沒有怎么在意。這幾天有人在我們自己的性能測試工具上面問了這個問題,我才陡然發現,原來我們也有。原文性能測試工具的問題
?
作者:唐劉
很早之前就看過 Gil 大神的一篇文章《Your Load Generator Is Probably Lying To You - Take The Red Pill And Find Out Why》,里面提到了性能測試工具 coordinated omission 的問題,但當時并沒有怎么在意。這幾天有人在我們自己的性能測試工具 go-ycsb (https://github.com/pingcap/go-ycsb/issues/26)上面問了這個問題,我才陡然發現,原來我們也有。
什么是 coordinated omission首先來說說什么是 coordinated omission。對于絕大多數 benchmark 工具來說,通常都是這樣的模型——啟動多個線程,每個線程依次的發送 request,接受 response,然后繼續下一次的發送。我們記錄的 latency 通常就是 response time - request time。這個看起來很 make sense,但實際是有問題的。
一個簡單的例子,當我們去 KFC 買炸雞,然后我們排在了一個隊伍后面,前面有 3 個人,開始 2 個人都好快,30 秒搞定,然后第三個墨跡了半天,花了 5 分鐘,然后到我了,30 秒搞定。對于我來說,我絕對不會認為我的 latency 是 30 秒,而是會算上排隊的時間 2 x 30 + 300,加上服務時間 30 秒,所以我的總的時間耗時是 390 秒。這里不知道大家看到了區別了沒有,就是市面上大多數的性能測試工具,其實用的是服務時間,但并沒有算上等待時間。
再來看一個例子,假設我們需要性能測試工具按照 10 ops/sec 的頻繁發送請求,也就是希望每 100 ms 發送一個。前面 9 個請求,每個都是 50 us 就返回了,但第 10 個請求持續了 1 s,而后面的又是 50 us。可以明顯地看到,在 1 s 那里,系統出現了卡頓,但這時候其實只有 1 個請求發上去,并沒有很好地對系統進行測試。
YCSB對于第一個排隊的例子,為了更好的計算 latency,YCSB 引入了一個 intended time 的概念,即記錄下操作實際的排隊時間。它使用了一個 local thread 變量,在 throttle 的時候,記錄:
private void throttleNanos(long startTimeNanos) { //throttle the operations if (_targetOpsPerMs > 0) { // delay until next tick long deadline = startTimeNanos + _opsdone*_targetOpsTickNs; sleepUntil(deadline); _measurements.setIntendedStartTimeNs(deadline); } }
然后每次操作的時候,使用 intended time 計算排隊時間:
public Status read(String table, String key, Setfields, Map result) { try (final TraceScope span = tracer.newScope(scopeStringRead)) { long ist = measurements.getIntendedtartTimeNs(); long st = System.nanoTime(); Status res = db.read(table, key, fields, result); long en = System.nanoTime(); measure("READ", res, ist, st, en); measurements.reportStatus("READ", res); return res; } }
需要注意,只有 YCSB 開啟了 target,intended time 才有作用。
我當初在看 YCSB 代碼的時候,一直沒搞明白為什么會有兩種時間,而且也不知道 intended time 到底是什么,后來重新回顧了 coordinated omission 才清楚。也就是說 YCSB 通過 intended time 來計算排隊時間。
但 YCSB 還是沒解決上面說的第二個問題,如果系統真的出現了卡主,測試客戶端仍然會跟著卡主,因為是同步發送請求的。在網上搜索了一下,看到了一篇 Paper《Coordinated Omission in NoSQL Database Benchmarking》,里面提到了將同步改成異步的方式,也就是說,每次的任務是一個 Future,首先根據 target 按照頻率發 Future 就行,至于這個 Future 什么時候完成,后面再說。而且因為是異步的,所以并不會卡主后面的請求。
Go YCSB那么具體到 go-ycsb,我們如何解決這個問題呢?我現在唯一能想到的就是利用 Go 的 goroutine,按照一定的頻率去生成 goroutine,執行測試。當然 Go 自身也會有調度的開銷,這里也需要排除。如果要測試的服務出現了卡頓,就會導致大量的 goroutine 沒法釋放,最終 OOM。雖然這樣子看起來比較殘暴,但這才是符合預期的。
這個只是一個想法,具體還沒做。一個原因是不同于其他語言,Go 的 goroutine 其實天生就能開很多,所以通常我都是上千并發進行測試的,假設我們有 1000 個并發,按照 1 ms 一次的頻率,其實也就等同于每個 goroutine 依次發送了。當然,有總比沒有好,如果你對這塊感興趣,歡迎給我們提交 PR,或者給我發郵件詳細討論 tl@pingcap.com。
原文:性能測試工具的 Coordinated Omission 問題
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/17766.html
摘要:使用時調用類的方法,該方法的描述是可以看出,該方法返回的是類型的結果,結果記錄的是至今經過的毫秒數。關于類,可以很自由的定制表現形式,年月日時分秒,時間格式,。。。 序 初涉江湖,還望海涵!寫點東西,純粹是因為個人的記憶能力較弱,寫些筆記罷了,若有錯誤還望雅正! 對Android中的時間獲取做個記錄,以下為結果! showImg(https://segmentfault.com/img...
閱讀 2006·2021-09-22 16:05
閱讀 9310·2021-09-22 15:03
閱讀 2885·2019-08-30 15:53
閱讀 1702·2019-08-29 11:15
閱讀 911·2019-08-26 13:52
閱讀 2353·2019-08-26 11:32
閱讀 1806·2019-08-26 10:38
閱讀 2567·2019-08-23 17:19