[ 
https://issues.apache.org/jira/browse/HBASE-25975?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17364618#comment-17364618
 ] 

Andrew Kyle Purtell edited comment on HBASE-25975 at 6/17/21, 2:16 AM:
-----------------------------------------------------------------------

Latest code with better microbenchmark, measuring exactly the time to call 
region.batchMutate() at each iteration. Times are per op, measured in nanos, 
converted to milliseconds for printing.

"0% contention case" -- All row keys in submitted requests are unique, so 
should never overlap in the same clock tick. Differences in these values from 
the baseline represent a combination of system variance and the additional 
overheads introduced by the patch. 

"100% contention case" -- All requests have the same duplicate set of row keys, 
so should always overlap in the same clock tick. You can clearly see the 
application of the constraint in the increases of MAX time, as expected. 

Baseline:
{noformat}
   1 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0561 
p99=0.0561, p999=0.0561 max=0.3001
   2 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0552 
p99=0.0564, p999=0.0564 max=1.0601
   4 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0686 
p99=0.0692, p999=0.0692 max=0.9828
   8 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0792 
p99=0.0813, p999=0.0813 max=1.3901
  16 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1197 
p99=0.1296, p999=0.1297 max=1.9159
  32 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1318 
p99=0.1414, p999=0.1415 max=4.8060
   1 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0608 
p99=0.0608, p999=0.0609 max=0.3793
   2 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0533 
p99=0.0559, p999=0.0559 max=0.4041
   4 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0603 
p99=0.0612, p999=0.0612 max=0.4097
   8 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1045 
p99=0.1121, p999=0.1121 max=0.8509
  16 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1334 
p99=0.1422, p999=0.1426 max=1.2274
  32 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1301 
p99=0.1399, p999=0.1400 max=2.9175
   1 threads  100 non-contended rows  100 iterations, ms/op: p50=0.1789 
p99=0.1789, p999=0.1789 max=0.4747
   2 threads  100 non-contended rows  100 iterations, ms/op: p50=0.1709 
p99=0.1742, p999=0.1743 max=0.6043
   4 threads  100 non-contended rows  100 iterations, ms/op: p50=0.1820 
p99=0.1897, p999=0.1898 max=2.5493
   8 threads  100 non-contended rows  100 iterations, ms/op: p50=0.2809 
p99=0.2856, p999=0.2857 max=4.1059
  16 threads  100 non-contended rows  100 iterations, ms/op: p50=0.4268 
p99=0.4393, p999=0.4394 max=5.5858
  32 threads  100 non-contended rows  100 iterations, ms/op: p50=0.6382 
p99=0.7335, p999=0.7338 max=16.4132
   1 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.5447 
p99=1.5447, p999=1.5448 max=2.4460
   2 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.6133 
p99=1.6489, p999=1.6493 max=10.4490
   4 threads 1000 non-contended rows  100 iterations, ms/op: p50=2.1818 
p99=2.2960, p999=2.2995 max=23.4926
   8 threads 1000 non-contended rows  100 iterations, ms/op: p50=2.3715 
p99=2.4573, p999=2.4615 max=33.7535
  16 threads 1000 non-contended rows  100 iterations, ms/op: p50=4.3571 
p99=4.4556, p999=4.4600 max=111.8534
  32 threads 1000 non-contended rows  100 iterations, ms/op: p50=4.4922 
p99=5.4098, p999=5.4190 max=225.4612
{noformat}

With RowCommitSequencer 0% contention case: 
{noformat}
   1 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1207 
p99=0.1207, p999=0.1209 max=1.8813
   2 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1048 
p99=0.1102, p999=0.1103 max=2.1397
   4 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1166 
p99=0.1312, p999=0.1315 max=1.7879
   8 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1331 
p99=0.1440, p999=0.1443 max=3.7075
  16 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1464 
p99=0.1697, p999=0.1704 max=1.9381
  32 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1386 
p99=0.1524, p999=0.1525 max=2.3399
   1 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0690 
p99=0.0690, p999=0.0691 max=1.5870
   2 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1142 
p99=0.1170, p999=0.1171 max=1.7043
   4 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0944 
p99=0.0959, p999=0.0959 max=1.7438
   8 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1086 
p99=0.1111, p999=0.1111 max=1.9832
  16 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1259 
p99=0.1396, p999=0.1398 max=1.7491
  32 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1155 
p99=0.1261, p999=0.1264 max=4.7331
   1 threads  100 non-contended rows  100 iterations, ms/op: p50=0.1732 
p99=0.1732, p999=0.1733 max=1.6654
   2 threads  100 non-contended rows  100 iterations, ms/op: p50=0.2309 
p99=0.2325, p999=0.2326 max=1.8260
   4 threads  100 non-contended rows  100 iterations, ms/op: p50=0.2475 
p99=0.2778, p999=0.2785 max=3.4691
   8 threads  100 non-contended rows  100 iterations, ms/op: p50=0.2914 
p99=0.3106, p999=0.3107 max=5.4343
  16 threads  100 non-contended rows  100 iterations, ms/op: p50=0.4262 
p99=0.4465, p999=0.4472 max=11.6418
  32 threads  100 non-contended rows  100 iterations, ms/op: p50=0.6965 
p99=0.7206, p999=0.7213 max=15.0728
   1 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.4351 
p99=1.4351, p999=1.4358 max=15.4978
   2 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.6366 
p99=1.6577, p999=1.6582 max=4.2604
   4 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.9030 
p99=2.0894, p999=2.0909 max=21.2956
   8 threads 1000 non-contended rows  100 iterations, ms/op: p50=2.5048 
p99=2.6549, p999=2.6581 max=33.1727
  16 threads 1000 non-contended rows  100 iterations, ms/op: p50=4.4060 
p99=4.8365, p999=4.8433 max=108.4194
  32 threads 1000 non-contended rows  100 iterations, ms/op: p50=4.7558 
p99=5.9772, p999=5.9816 max=175.4064
{noformat}

With RowCommitSequencer 100% contention case: 
{noformat}
   1 threads    1 contended rows  100 iterations, ms/op: p50=0.0582 p99=0.0582, 
p999=0.0584 max=3.0230
   2 threads    1 contended rows  100 iterations, ms/op: p50=0.0812 p99=0.0825, 
p999=0.0825 max=4.1251
   4 threads    1 contended rows  100 iterations, ms/op: p50=0.0884 p99=0.1229, 
p999=0.1230 max=13.6791
   8 threads    1 contended rows  100 iterations, ms/op: p50=0.1205 p99=0.1260, 
p999=0.1260 max=31.4853
  16 threads    1 contended rows  100 iterations, ms/op: p50=0.1221 p99=0.1411, 
p999=0.1414 max=115.6539
  32 threads    1 contended rows  100 iterations, ms/op: p50=0.1067 p99=0.1659, 
p999=0.1691 max=233.7836
   1 threads   10 contended rows  100 iterations, ms/op: p50=0.1023 p99=0.1023, 
p999=0.1024 max=1.6838
   2 threads   10 contended rows  100 iterations, ms/op: p50=0.0663 p99=0.0701, 
p999=0.0702 max=5.3990
   4 threads   10 contended rows  100 iterations, ms/op: p50=0.0837 p99=0.1030, 
p999=0.1033 max=10.6789
   8 threads   10 contended rows  100 iterations, ms/op: p50=0.0928 p99=0.1494, 
p999=0.1496 max=32.4364
  16 threads   10 contended rows  100 iterations, ms/op: p50=0.1625 p99=0.1759, 
p999=0.1762 max=133.6848
  32 threads   10 contended rows  100 iterations, ms/op: p50=0.1650 p99=0.1946, 
p999=0.1948 max=245.6805
   1 threads  100 contended rows  100 iterations, ms/op: p50=0.2607 p99=0.2607, 
p999=0.2608 max=2.3032
   2 threads  100 contended rows  100 iterations, ms/op: p50=0.2449 p99=0.2583, 
p999=0.2584 max=4.0113
   4 threads  100 contended rows  100 iterations, ms/op: p50=0.2803 p99=0.3129, 
p999=0.3129 max=104.3184
   8 threads  100 contended rows  100 iterations, ms/op: p50=0.2778 p99=0.3147, 
p999=0.3150 max=42.7154
  16 threads  100 contended rows  100 iterations, ms/op: p50=0.3228 p99=0.3680, 
p999=0.3685 max=105.5341
  32 threads  100 contended rows  100 iterations, ms/op: p50=0.3124 p99=0.3333, 
p999=0.3334 max=222.9051
   1 threads 1000 contended rows  100 iterations, ms/op: p50=1.5311 p99=1.5311, 
p999=1.5314 max=2.3854
   2 threads 1000 contended rows  100 iterations, ms/op: p50=1.2614 p99=1.2890, 
p999=1.2893 max=6.5509
   4 threads 1000 contended rows  100 iterations, ms/op: p50=1.8523 p99=1.9340, 
p999=1.9349 max=22.0056
   8 threads 1000 contended rows  100 iterations, ms/op: p50=1.8517 p99=1.9559, 
p999=1.9563 max=36.0947
  16 threads 1000 contended rows  100 iterations, ms/op: p50=1.9385 p99=1.9811, 
p999=1.9815 max=124.6219
  32 threads 1000 contended rows  100 iterations, ms/op: p50=2.3027 p99=2.8692, 
p999=2.8748 max=270.6748
{noformat}



was (Author: apurtell):
Latest code with better microbenchmark, measuring exactly the time to call 
region.batchMutate() at each iteration. Times are per op, measured in nanos, 
converted to milliseconds for printing.

"0% contention case" -- All row keys in submitted requests are unique, so 
should never overlap in the same clock tick. Differences in these values from 
the baseline represent a combination of system variance and the additional 
overheads introduced by the patch. 

"100% contention case" -- All requests have the same duplicate set of row keys, 
so should always overlap in the same clock tick. You can clearly see the 
application of the constraint in the increases of MAX time, as expected. 

Baseline:
{noformat}
   1 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0561 
p99=0.0561, p999=0.0561 max=0.3001
   2 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0552 
p99=0.0564, p999=0.0564 max=1.0601
   4 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0686 
p99=0.0692, p999=0.0692 max=0.9828
   8 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0792 
p99=0.0813, p999=0.0813 max=1.3901
  16 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1197 
p99=0.1296, p999=0.1297 max=1.9159
  32 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1318 
p99=0.1414, p999=0.1415 max=4.8060
   1 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0608 
p99=0.0608, p999=0.0609 max=0.3793
   2 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0533 
p99=0.0559, p999=0.0559 max=0.4041
   4 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0603 
p99=0.0612, p999=0.0612 max=0.4097
   8 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1045 
p99=0.1121, p999=0.1121 max=0.8509
  16 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1334 
p99=0.1422, p999=0.1426 max=1.2274
  32 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1301 
p99=0.1399, p999=0.1400 max=2.9175
   1 threads  100 non-contended rows  100 iterations, ms/op: p50=0.1789 
p99=0.1789, p999=0.1789 max=0.4747
   2 threads  100 non-contended rows  100 iterations, ms/op: p50=0.1709 
p99=0.1742, p999=0.1743 max=0.6043
   4 threads  100 non-contended rows  100 iterations, ms/op: p50=0.1820 
p99=0.1897, p999=0.1898 max=2.5493
   8 threads  100 non-contended rows  100 iterations, ms/op: p50=0.2809 
p99=0.2856, p999=0.2857 max=4.1059
  16 threads  100 non-contended rows  100 iterations, ms/op: p50=0.4268 
p99=0.4393, p999=0.4394 max=5.5858
  32 threads  100 non-contended rows  100 iterations, ms/op: p50=0.6382 
p99=0.7335, p999=0.7338 max=16.4132
   1 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.5447 
p99=1.5447, p999=1.5448 max=2.4460
   2 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.6133 
p99=1.6489, p999=1.6493 max=10.4490
   4 threads 1000 non-contended rows  100 iterations, ms/op: p50=2.1818 
p99=2.2960, p999=2.2995 max=23.4926
   8 threads 1000 non-contended rows  100 iterations, ms/op: p50=2.3715 
p99=2.4573, p999=2.4615 max=33.7535
  16 threads 1000 non-contended rows  100 iterations, ms/op: p50=4.3571 
p99=4.4556, p999=4.4600 max=111.8534
  32 threads 1000 non-contended rows  100 iterations, ms/op: p50=4.4922 
p99=5.4098, p999=5.4190 max=225.4612
{noformat}

With RowCommitSequencer 0% contention case: 
{noformat}
   1 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1108 
p99=0.1108, p999=0.1108 max=3.3199
   2 threads    1 non-contended rows  100 iterations, ms/op: p50=0.0902 
p99=0.1213, p999=0.1216 max=1.7926
   4 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1287 
p99=0.1346, p999=0.1347 max=1.8199
   8 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1200 
p99=0.1365, p999=0.1367 max=1.9109
  16 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1298 
p99=0.1352, p999=0.1352 max=1.9318
  32 threads    1 non-contended rows  100 iterations, ms/op: p50=0.1315 
p99=0.1522, p999=0.1525 max=2.6332
   1 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0595 
p99=0.0595, p999=0.0596 max=1.6384
   2 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0684 
p99=0.0692, p999=0.0692 max=1.4759
   4 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0918 
p99=0.0973, p999=0.0974 max=1.6548
   8 threads   10 non-contended rows  100 iterations, ms/op: p50=0.0929 
p99=0.1042, p999=0.1043 max=1.7982
  16 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1206 
p99=0.1313, p999=0.1313 max=1.7856
  32 threads   10 non-contended rows  100 iterations, ms/op: p50=0.1198 
p99=0.1400, p999=0.1400 max=4.4632
   1 threads  100 non-contended rows  100 iterations, ms/op: p50=0.2106 
p99=0.2106, p999=0.2106 max=2.2026
   2 threads  100 non-contended rows  100 iterations, ms/op: p50=0.1910 
p99=0.2283, p999=0.2287 max=2.0957
   4 threads  100 non-contended rows  100 iterations, ms/op: p50=0.2774 
p99=0.2824, p999=0.2824 max=3.6852
   8 threads  100 non-contended rows  100 iterations, ms/op: p50=0.3029 
p99=0.3219, p999=0.3224 max=4.0838
  16 threads  100 non-contended rows  100 iterations, ms/op: p50=0.3813 
p99=0.4126, p999=0.4129 max=7.7517
  32 threads  100 non-contended rows  100 iterations, ms/op: p50=0.6552 
p99=0.7831, p999=0.7837 max=16.8252
   1 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.4204 
p99=1.4204, p999=1.4209 max=17.4774
   2 threads 1000 non-contended rows  100 iterations, ms/op: p50=1.6563 
p99=1.6654, p999=1.6662 max=22.6109
   4 threads 1000 non-contended rows  100 iterations, ms/op: p50=2.1168 
p99=2.1457, p999=2.1463 max=22.9576
   8 threads 1000 non-contended rows  100 iterations, ms/op: p50=2.4217 
p99=2.6266, p999=2.6272 max=28.9599
  16 threads 1000 non-contended rows  100 iterations, ms/op: p50=4.3466 
p99=4.4730, p999=4.4732 max=126.3769
  32 threads 1000 non-contended rows  100 iterations, ms/op: p50=5.3735 
p99=5.7779, p999=5.7862 max=233.5676
{noformat}

With RowCommitSequencer 100% contention case: 
{noformat}
   1 threads    1 contended rows  100 iterations, ms/op: p50=0.0558 p99=0.0558, 
p999=0.0562 max=1.7508
   2 threads    1 contended rows  100 iterations, ms/op: p50=0.0683 p99=0.0808, 
p999=0.0810 max=4.3242
   4 threads    1 contended rows  100 iterations, ms/op: p50=0.0946 p99=0.1012, 
p999=0.1013 max=16.4388
   8 threads    1 contended rows  100 iterations, ms/op: p50=0.1177 p99=0.1249, 
p999=0.1251 max=32.6156
  16 threads    1 contended rows  100 iterations, ms/op: p50=0.1444 p99=0.1591, 
p999=0.1596 max=91.9189
  32 threads    1 contended rows  100 iterations, ms/op: p50=0.1805 p99=1.2789, 
p999=1.2793 max=230.0010
   1 threads   10 contended rows  100 iterations, ms/op: p50=0.0756 p99=0.0756, 
p999=0.0757 max=1.6382
   2 threads   10 contended rows  100 iterations, ms/op: p50=0.0800 p99=0.0837, 
p999=0.0838 max=5.7082
   4 threads   10 contended rows  100 iterations, ms/op: p50=0.0972 p99=0.1088, 
p999=0.1090 max=13.2040
   8 threads   10 contended rows  100 iterations, ms/op: p50=0.1042 p99=0.1423, 
p999=0.1431 max=28.6613
  16 threads   10 contended rows  100 iterations, ms/op: p50=0.1571 p99=0.1633, 
p999=0.1633 max=102.7910
  32 threads   10 contended rows  100 iterations, ms/op: p50=0.1630 p99=1.2682, 
p999=1.2702 max=248.9046
   1 threads  100 contended rows  100 iterations, ms/op: p50=0.2042 p99=0.2042, 
p999=0.2044 max=2.1793
   2 threads  100 contended rows  100 iterations, ms/op: p50=0.2054 p99=0.2342, 
p999=0.2348 max=4.2469
   4 threads  100 contended rows  100 iterations, ms/op: p50=0.2488 p99=0.2831, 
p999=0.2838 max=17.7257
   8 threads  100 contended rows  100 iterations, ms/op: p50=0.2649 p99=0.3028, 
p999=0.3029 max=44.8713
  16 threads  100 contended rows  100 iterations, ms/op: p50=0.2779 p99=0.3044, 
p999=0.3049 max=99.4218
  32 threads  100 contended rows  100 iterations, ms/op: p50=0.3135 p99=0.3263, 
p999=0.3264 max=355.3952
   1 threads 1000 contended rows  100 iterations, ms/op: p50=1.5648 p99=1.5648, 
p999=1.5649 max=2.6714
   2 threads 1000 contended rows  100 iterations, ms/op: p50=1.5051 p99=1.6097, 
p999=1.6111 max=83.0051
   4 threads 1000 contended rows  100 iterations, ms/op: p50=1.8555 p99=1.8793, 
p999=1.8794 max=20.8204
   8 threads 1000 contended rows  100 iterations, ms/op: p50=1.8331 p99=1.9490, 
p999=1.9494 max=33.7916
  16 threads 1000 contended rows  100 iterations, ms/op: p50=1.9460 p99=2.0191, 
p999=2.0193 max=187.0420
  32 threads 1000 contended rows  100 iterations, ms/op: p50=2.4060 p99=2.6065, 
p999=2.6118 max=302.2282
{noformat}


> Row commit sequencer
> --------------------
>
>                 Key: HBASE-25975
>                 URL: https://issues.apache.org/jira/browse/HBASE-25975
>             Project: HBase
>          Issue Type: Sub-task
>          Components: regionserver
>            Reporter: Andrew Kyle Purtell
>            Assignee: Andrew Kyle Purtell
>            Priority: Major
>             Fix For: 3.0.0-alpha-1, 2.5.0
>
>         Attachments: HBASE-25975-c4cf83ce.pdf
>
>
> Use a row commit sequencer in HRegion to ensure that only the operations that 
> mutate disjoint sets of rows are able to commit within the same clock tick. 
> This maintains the invariant that more than one mutation to a given row will 
> never be committed in the same clock tick.
> Callers will first acquire row locks for the row(s) the pending mutation will 
> mutate. Then they will use RowCommitSequencer.getRowSequence to ensure that 
> the set of rows about to be mutated do not overlap with those for any other 
> pending mutations in the current clock tick. If an overlap is identified, 
> getRowSequence will yield and loop until there is no longer an overlap and 
> the caller's pending mutation can succeed.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to