Skip to content

Implement optimized version of PinotByteBuffer.#5058

Closed
siddharthteotia wants to merge 1 commit intoapache:masterfrom
siddharthteotia:unsafe
Closed

Implement optimized version of PinotByteBuffer.#5058
siddharthteotia wants to merge 1 commit intoapache:masterfrom
siddharthteotia:unsafe

Conversation

@siddharthteotia
Copy link
Contributor

@siddharthteotia siddharthteotia commented Feb 7, 2020

We can directly work on the address of the underlying memory chunk by-passing all the chain of function calls and do get/set at the absolute address computed as starting virtual address of underlying memory + offset.

Two implementations are provided:

  • PinotNativeUnsafeByteBuffer
  • PinotNonNativeUnsafeByteBuffer

We can directly work on the addresss of the underlying memory chunk
bypassing all the chain of function calls and do get/set at
the absolute address computed as starting virtual address of
underlying memory + offset.

Two implementations are provided

PinotNativeUnsafeByteBuffer
PinotNonNativeUnsafeByteBuffer
@siddharthteotia
Copy link
Contributor Author

siddharthteotia commented Feb 7, 2020

Benchmark Mode Cnt Score Unit
BenchmarkPinotByteBufferOptimized.pinotNativeUnsafeByteBufferReadRandom avgt 5 0.961 ns/op
BenchmarkPinotByteBufferOptimized.pinotNativeUnsafeByteBufferReadSequential avgt 5 0.357 ns/op
BenchmarkPinotByteBufferOptimized.pinotNativeUnsafeByteBufferWriteRandom avgt 5 210873617 ns/op
BenchmarkPinotByteBufferOptimized.pinotNativeUnsafeByteBufferWriteSequential avgt 5 18528396.13 ns/op
BenchmarkPinotByteBufferOptimized.pinotByteBufferReadRandom avgt 5 21692687.27 ns/op
BenchmarkPinotByteBufferOptimized.pinotByteBufferReadSequential avgt 5 9.684 ns/op
BenchmarkPinotByteBufferOptimized.pinotByteBufferWriteRandom avgt 5 382048235.7 ns/op
BenchmarkPinotByteBufferOptimized.pinotByteBufferWriteSequential avgt 5 41911001.94 ns/op

@codecov-io
Copy link

Codecov Report

Merging #5058 into master will increase coverage by 0.13%.
The diff coverage is 69.53%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #5058      +/-   ##
============================================
+ Coverage     58.53%   58.67%   +0.13%     
  Complexity       12       12              
============================================
  Files          1183     1185       +2     
  Lines         63213    63515     +302     
  Branches       9297     9317      +20     
============================================
+ Hits          37003    37267     +264     
+ Misses        23501    23467      -34     
- Partials       2709     2781      +72
Impacted Files Coverage Δ Complexity Δ
...che/pinot/core/segment/memory/PinotByteBuffer.java 79.72% <ø> (ø) 0 <0> (ø) ⬇️
...re/segment/memory/PinotNativeUnsafeByteBuffer.java 69.53% <69.53%> (ø) 0 <0> (?)
...segment/memory/PinotNonNativeUnsafeByteBuffer.java 69.53% <69.53%> (ø) 0 <0> (?)
.../org/apache/pinot/client/PinotClientException.java 33.33% <0%> (-33.34%) 0% <0%> (ø)
...a/manager/realtime/RealtimeSegmentDataManager.java 50% <0%> (-25%) 0% <0%> (ø)
...inot/client/JsonAsyncHttpPinotClientTransport.java 62% <0%> (-14%) 0% <0%> (ø)
...e/impl/dictionary/LongOnHeapMutableDictionary.java 57.31% <0%> (-13.42%) 0% <0%> (ø)
...r/dociditerators/RangelessBitmapDocIdIterator.java 72.22% <0%> (-11.12%) 0% <0%> (ø)
...pinot/broker/api/resources/PinotClientRequest.java 23.4% <0%> (-8.52%) 0% <0%> (ø)
.../impl/dictionary/FloatOnHeapMutableDictionary.java 70.73% <0%> (-6.1%) 0% <0%> (ø)
... and 26 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1f4605b...603744f. Read the comment docs.

@xiangfu0
Copy link
Contributor

xiangfu0 commented Feb 7, 2020

This is nice ! Please also test if this compile and running with different java 8+ versions and JDKs.

static PinotNativeUnsafeByteBuffer mapFile(File file, boolean readOnly, long offset, int size)
throws IOException {
if (readOnly) {
try (FileChannel fileChannel = new RandomAccessFile(file, "r").getChannel()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: you can just have the read/write mode assigned based on readOnly flag, and still have the fileChannel.map() and new PinotNativeUnsafeByteBuffer() outside the if check.

}

@Override
public byte getByte(int offset) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these api's seem common in both classes, may be push up to a base class?

@Measurement(iterations = 5)
@Fork(1)
@State(Scope.Benchmark)
public class BenchmarkPinotByteBuffer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please publish the results of this benchmark and add it to the PR description?



@ThreadSafe
public class PinotNativeUnsafeByteBuffer extends PinotDataBuffer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the caller would need to know and decide whether to use Native vs Non-native? Do you think it would be better to have that switch inside the implementation (so one impl that implements both), so that callers don't need to worry about byte ordering?

@kishoreg
Copy link
Member

kishoreg commented May 9, 2020

@siddharthteotia

@Jackie-Jiang
Copy link
Contributor

Re-implemented in #10528

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants