В этом посте:
- Запуск JLBH с учетом и без учета согласованного упущения
- Пример численного воздействия скоординированного упущения
- Дискуссия об управлении потоком
Вот пример, который я использовал при описании того, что было бы, если бы вы измеряли без учета скоординированного упущения:
Представим, что вы ждете поезд и задерживаетесь на станции на час, потому что поезд перед вами опаздывает. Тогда давайте представим, что вы садитесь в поезд на час позже, а поезду обычно требуется полчаса, чтобы добраться до пункта назначения. Если вы не учитываете согласованное упущение, вы не будете считать, что понесли какую-либо задержку, поскольку ваше путешествие заняло ровно столько времени, сколько вы ожидали на станции в течение часа перед отправлением!
Но это именно то, что вы делаете, когда запускаете микро-тест. Вы время каждого «путешествия», а не время ожидания.
И правда в том, что это абсолютно нормально для микро-теста. Но это не хорошо, когда вы хотите измерить задержку приложения.
По умолчанию измерения JLBH от начала до конца учитывают скоординированное упущение, хотя у вас есть настройка для его измерения без учета скоординированного пропуска.
Я написал этот простой тест, чтобы показать, насколько драматичным может быть эффект, связанный с согласованным упущением.
В этом примере после каждых 10 000 итераций мы добавляем задержку в миллисекунду:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package org.latency.spike; import net.openhft.chronicle.core.Jvm; import net.openhft.chronicle.core.jlbh.JLBH; import net.openhft.chronicle.core.jlbh.JLBHOptions; import net.openhft.chronicle.core.jlbh.JLBHTask; /** * A simple JLBH example to show the effects od accounting for co-ordinated omission. * Toggle the accountForCoordinatedOmission to see results. */ public class SimpleSpikeJLBHTask implements JLBHTask { private int count = 0 ; private JLBH lth; public static void main(String[] args){ JLBHOptions lth = new JLBHOptions() .warmUpIterations(40_000) .iterations(1_100_000) .throughput(100_000) .runs( 3 ) .recordOSJitter( true ) .accountForCoordinatedOmmission( true ) .jlbhTask( new SimpleSpikeJLBHTask()); new JLBH(lth).start(); } @Override public void run( long startTimeNS) { if ((count++)%10_000== 0 ){ //pause a while Jvm.busyWaitMicros( 1000 ); } lth.sample(System.nanoTime() - startTimeNS); } @Override public void init(JLBH lth) { this .lth = lth; } } |
Если вы установите значение coordinatedOmission(false)
вы получите этот профиль — как и ожидалось, задержка в миллисекундах может быть видна только на самом высоком процентиле, начиная с 99,99-го процентиля и выше. Или, так сказать, это влияет только на одну из каждых 10 итераций — не удивительно.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
Warm up complete (40000 iterations took 0.046s) -------------------------------- BENCHMARK RESULTS (RUN 1) ----------- Run time : 11.593s Correcting for co-ordinated: false Target throughput:100000 /s = 1 message every 10us End to End: (1,100,000) 50 /90 99 /99 .9 99.99 /99 .999 - worst was 0.11 / 0.13 0.20 / 0.33 999 / 999 - 1,930 OS Jitter (14,986) 50 /90 99 /99 .9 99.99 - worst was 8.4 / 15 68 / 1,080 3,210 - 4,330 ---------------------------------------------------------------------- -------------------------------- BENCHMARK RESULTS (RUN 2) ----------- Run time : 11.49s Correcting for co-ordinated: false Target throughput:100000 /s = 1 message every 10us End to End: (1,100,000) 50 /90 99 /99 .9 99.99 /99 .999 - worst was 0.11 / 0.13 0.16 / 0.28 999 / 999 - 999 OS Jitter (13,181) 50 /90 99 /99 .9 99.99 - worst was 8.4 / 12 36 / 62 270 - 573 ---------------------------------------------------------------------- -------------------------------- BENCHMARK RESULTS (RUN 3) ----------- Run time : 11.494s Correcting for co-ordinated: false Target throughput:100000 /s = 1 message every 10us End to End: (1,100,000) 50 /90 99 /99 .9 99.99 /99 .999 - worst was 0.11 / 0.13 0.16 / 0.26 999 / 999 - 1,030 OS Jitter (13,899) 50 /90 99 /99 .9 99.99 - worst was 8.4 / 13 42 / 76 160 - 541 ---------------------------------------------------------------------- -------------------------------- SUMMARY (end to end)----------------- Percentile run1 run2 run3 % Variation 50: 0.11 0.11 0.11 0.00 90: 0.13 0.13 0.13 0.00 99: 0.20 0.16 0.16 3.31 99.9: 0.33 0.28 0.26 3.88 99.99: 999.42 999.42 999.42 0.00 99.999: 999.42 999.42 999.42 0.00 worst: 1933.31 999.42 1032.19 2.14 ---------------------------------------------------------------------- |
Но если вы установите значение coordinatedOmission(true)
вы увидите истинный эффект этой задержки.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
Warm up complete (40000 iterations took 0.044s) -------------------------------- BENCHMARK RESULTS (RUN 1) ----------- Run time : 11.0s Correcting for co-ordinated: true Target throughput:100000 /s = 1 message every 10us End to End: (1,100,000) 50 /90 99 /99 .9 99.99 /99 .999 - worst was 0.11 / 0.17 385 / 1,930 4,590 / 5,370 - 5,370 OS Jitter (13,605) 50 /90 99 /99 .9 99.99 - worst was 8.4 / 15 68 / 1,080 5,110 - 5,900 ---------------------------------------------------------------------- -------------------------------- BENCHMARK RESULTS (RUN 2) ----------- Run time : 11.0s Correcting for co-ordinated: true Target throughput:100000 /s = 1 message every 10us End to End: (1,100,000) 50 /90 99 /99 .9 99.99 /99 .999 - worst was 0.12 / 0.18 42 / 901 999 / 999 - 1,030 OS Jitter (13,156) 50 /90 99 /99 .9 99.99 - worst was 8.4 / 13 38 / 68 209 - 467 ---------------------------------------------------------------------- -------------------------------- BENCHMARK RESULTS (RUN 3) ----------- Run time : 11.0s Correcting for co-ordinated: true Target throughput:100000 /s = 1 message every 10us End to End: (1,100,000) 50 /90 99 /99 .9 99.99 /99 .999 - worst was 0.12 / 0.18 46 / 901 999 / 999 - 999 OS Jitter (13,890) 50 /90 99 /99 .9 99.99 - worst was 8.4 / 14 44 / 80 250 - 1,870 ---------------------------------------------------------------------- -------------------------------- SUMMARY (end to end)----------------- Percentile run1 run2 run3 % Variation 50: 0.11 0.12 0.12 0.00 90: 0.17 0.18 0.18 0.00 99: 385.02 41.98 46.08 6.11 99.9: 1933.31 901.12 901.12 0.00 99.99: 4587.52 999.42 999.42 0.00 99.999: 5373.95 999.42 999.42 0.00 worst: 5373.95 1032.19 999.42 2.14 ---------------------------------------------------------------------- |
На самом деле, одна из ста (не одна из 10 000) итераций затрагивается в некоторой степени. Вы также можете увидеть прогрессивный эффект латентности, когда вы возьмете процентили.
Это наглядно демонстрирует в цифрах, почему скоординированное упущение должно быть существенной частью вашего сравнительного анализа, особенно если вы не можете осуществлять управление потоком в своей программе. Контроль потока — это возможность перестать потреблять, если вы не успеваете, например, отталкивать пользователей от вашего сайта, если вы слишком заняты. Fix Engines не может управлять потоком, то есть вы не можете сказать рынку замедляться, потому что не можете идти в ногу! Программы, которые осуществляют управление потоком, ориентированы на потребителя, в то время как программы не обеспечивают управление потоком, ориентированы на производителя.
Учет скоординированного упущения идет рука об руку с возможностью установить задержку для определенной пропускной способности, что мы рассмотрим в следующем примере.
Ссылка: | Примеры 2 JLBH — Учет координированного пропуска от нашего партнера JCG Дэниела Шая в блоге Rational Java . |