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

Huang Kuan Hao updated HDDS-16350:
----------------------------------
    Description: 
RDBTable.getRangeKVs checks whether startKey exists with get(startKey) == null, 
a full point-get that materializes and then discards the value byte[], right 
before it.seek(startKey) lands on that same key.

Before:
if ((prefix == null || startKey.length > prefix.length)
    && get(startKey) == null) {
  // Key not found, return empty list
  return result;
}
it.seek(startKey);

seek() already positions the iterator and returns the landing entry without 
consuming it, so the existence check can reuse that entry instead of a separate 
get: startKey is present iff the landing key equals startKey.

After:
final KeyValue<byte[], byte[]> seeked
if ((prefix == null || startKey.length > prefix.length)
    && (seeked == null || !Arrays.equaey))) {
  // start key not found, return empty list
  return result;
}

This drops one point-get per getRangeKVs call plus the value byte[] it 
allocated only to discard. Behavior is unchanged: the loop still ng entry, and 
the empty-result pathfires on exactly the same inputs.

Microbenchmark (JMH, real RocksDB, 100k keys, 512-byte values, present start 
key), old (extra get) vs new (seek landing check), avg time / acall:

  page=1      1.62 -> 0.99 us    1136
  page=10     3.86 -> 3.39 us    6176 -> 5680 B/op
  page=100    27.6 -> 25.6 us    56576
  page=1000   254  -> 250  us    560581 -> 560085 B/op

The saving is exactly one point-get: a constant ~496 B/op and ~0.5-0.6 us per 
call, largest as a
fraction on small pages (~39% at page=e iteration cost as pages grow.

  was:
RDBTable.getRangeKVs checks whether startKey exists with get(startKey) == null, 
a full point-get that materializes and then discards the value byte[], 
immediately followed by it.seek(startKey).

Current:
if ((prefix == null || startKey.length > prefix.length)
    && get(startKey) == null) {
  // Key not found, return empty list
  return result;
}
it.seek(startKey);

isExist(byte[]) already answers this via keyMayExist (bloom filter) and only 
point-gets when keyMayExist is undecided, so it does not materialize the value 
in the common case and is exact. Fix: use !isExist(startKey). Behavior 
unchanged.


> Use isExist instead of a value get for the start-key check in 
> RDBTable.getRangeKVs
> ----------------------------------------------------------------------------------
>
>                 Key: HDDS-16350
>                 URL: https://issues.apache.org/jira/browse/HDDS-16350
>             Project: Apache Ozone
>          Issue Type: Improvement
>            Reporter: Huang Kuan Hao
>            Assignee: Huang Kuan Hao
>            Priority: Major
>
> RDBTable.getRangeKVs checks whether startKey exists with get(startKey) == 
> null, a full point-get that materializes and then discards the value byte[], 
> right before it.seek(startKey) lands on that same key.
> Before:
> if ((prefix == null || startKey.length > prefix.length)
>     && get(startKey) == null) {
>   // Key not found, return empty list
>   return result;
> }
> it.seek(startKey);
> seek() already positions the iterator and returns the landing entry without 
> consuming it, so the existence check can reuse that entry instead of a 
> separate get: startKey is present iff the landing key equals startKey.
> After:
> final KeyValue<byte[], byte[]> seeked
> if ((prefix == null || startKey.length > prefix.length)
>     && (seeked == null || !Arrays.equaey))) {
>   // start key not found, return empty list
>   return result;
> }
> This drops one point-get per getRangeKVs call plus the value byte[] it 
> allocated only to discard. Behavior is unchanged: the loop still ng entry, 
> and the empty-result pathfires on exactly the same inputs.
> Microbenchmark (JMH, real RocksDB, 100k keys, 512-byte values, present start 
> key), old (extra get) vs new (seek landing check), avg time / acall:
>   page=1      1.62 -> 0.99 us    1136
>   page=10     3.86 -> 3.39 us    6176 -> 5680 B/op
>   page=100    27.6 -> 25.6 us    56576
>   page=1000   254  -> 250  us    560581 -> 560085 B/op
> The saving is exactly one point-get: a constant ~496 B/op and ~0.5-0.6 us per 
> call, largest as a
> fraction on small pages (~39% at page=e iteration cost as pages grow.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to