[ 
https://issues.apache.org/jira/browse/HBASE-25975?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Andrew Kyle Purtell updated HBASE-25975:
----------------------------------------
    Comment: was deleted

(was: Attached as  [^JMH-25975-17614de8.pdf] a JMH based microbenchmark for 
just the RowCommitSequencer code. Results that indicate the floor of any 
performance impact. (Above earlier reported benchmarks measure all code called 
from HRegion#batchMutate and includes multithreaded cases.)

Highlights:

* The p99 of the single thread 1 row case is 75 ns, the p999 is 1068 ns, and 
the max is 141568 ns (0.142 ms).


* The p99 of the single thread 1000 row case is 79 ns, the p999 is 830 ns, and 
the max is 71040 ns (0.071 ms).


* The p99 of the 8 thread 1 row case is 36544 ns (0.037 ms), the p999 is 76032 
ns (0.076 ms), and the max is 4825088 ns (4.825 ms).


* The p99 of the 8 thread 1000 row case is 40960 ns (0.041 ms), the p999 is 
90624 ns (0.091 ms), and the max is 3928064 ns (3.928 ms).

(My test host has 8 real CPU threads.)

I also include profiler data captured by async-profiler, which confirms 
expected results:


Most time in the single threaded case is spent getting the system time 
(mach_absolute_time). We only do this once per operation in the real world but 
in the microbenchmark it is done at every iteration, as required to test the 
code, so this dominates as far as the profiler is concerned. So far so good.


checkAndAddRows is inlined into RowCommitSequencer#getRowSequence and 
getRowSequence takes more time as the batch size increases, and as well HashMap 
methods show up. This is expected, because the test-and-set of the row set for 
the clock tick is O(N*2) with respect to the number of rows in the batch 
mutation. 


For the case where I have all CPU cores concurrently accessing the same 
sequencer, the profiler shows that threads contend on the lock used to 
implement the critical section for the test-and-set of the current tick’s row 
set and the condvar where threads wait until the clock ticks forward if their 
operation conflicts with another that was already committed in the same tick. 
(Look for __psynch_cvwait.) Although there is no conflict in this test there is 
still thread synchronization on the lock. This is expected. Improving this 
requires introducing lockless design elements. I am not sure if a lockless 
design is possible. By making this behavior optional that would mitigate the 
performance impact to just those who need it.)

> 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: 2.5.0, 3.0.0-alpha-2
>
>
> 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