Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.

DL-45: DL should allow ByteBuf based API to avoid copying bytes array#151

Closed
sijie wants to merge 19 commits intoapache:masterfrom
sijie:zero_copy
Closed

DL-45: DL should allow ByteBuf based API to avoid copying bytes array#151
sijie wants to merge 19 commits intoapache:masterfrom
sijie:zero_copy

Conversation

@sijie
Copy link
Copy Markdown
Member

@sijie sijie commented Aug 22, 2017

Descriptions of the changes in this PR:

This change leverages the ByteBuf api introduced in bookkeeper 4.5.0. It will avoid copying bytes array between LogRecord and LogRecordSet/Entry, and avoid copying bytes from DL to BK client.

This change also bump the lz4 library to 1.3.0 to leverage the ByteBuffer binding.

@sijie sijie added this to the 0.5.0 milestone Aug 22, 2017
@sijie sijie self-assigned this Aug 22, 2017
@sijie sijie requested a review from mgodave August 22, 2017 19:12
@sijie
Copy link
Copy Markdown
Member Author

sijie commented Aug 22, 2017

/cc @leighst for review

This change doesn't include any benchmark result. I will have a subsequent change to have a micro-benchmark result to compare the serialization/deserialization performance.

Copy link
Copy Markdown

@eolivelli eolivelli left a comment

Choose a reason for hiding this comment

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

Great improvement, basically it is the switch to pooled and reference counted bytebufs

}

@Override
protected void finalize() throws Throwable {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Just to be curious, why are you using finalize?
I think that finalize is bad and legacy mechanism in Java and could lead in general to problems

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I know finalize is not a reliable and recommended way to release resource. However if I don't do finalize, there is no other way for me to release resources. or I have to change every classes that explicitly release the byte buf, this is going to a big change. also it is going to hard to change public structure like LogRecord to release references. it is going to break the API.

I will have a subsequent change to improve this. because I don't want to mix them in a big pull request.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 on this, seems like its not something we should do lightly

how are you planning to solve it?

Copy link
Copy Markdown
Contributor

@hellostreaming hellostreaming left a comment

Choose a reason for hiding this comment

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

+1.
Thanks for the great work.

@sijie
Copy link
Copy Markdown
Member Author

sijie commented Aug 30, 2017

@leighst @mgodave can any of you review this as well?

Copy link
Copy Markdown
Contributor

@leighst leighst left a comment

Choose a reason for hiding this comment

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

LGTM

EnvelopedEntry entry = new EnvelopedEntry(version, statsLogger);
entry.readFully(new DataInputStream(src));
return new ByteArrayInputStream(entry.getDecompressedPayload());
public static ByteBuf fromEnvlopedBuf(ByteBuf src, StatsLogger statsLogger)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

typo: fromEnvlopedBuf

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

fixed

}
int flags = src.readInt();
int codecCode = flags & COMPRESSION_CODEC_MASK;
int originDataLen = src.readInt();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do you mean "original"?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

changed to 'compressed'

this.buffer = new Buffer(initialBufferSize * 6 / 5);
this.writer = new LogRecord.Writer(new DataOutputStream(buffer));
this.buffer = PooledByteBufAllocator.DEFAULT.buffer(
Math.min(Math.max(initialBufferSize * 6 / 5, HEADER_LENGTH), MAX_LOGRECORDSET_SIZE),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why this *6/5 ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I don't remember what was exactly the reason that we used *6/5. We can probably remove it.


if (Type.NONE == codec) {
// update version
buffer.setByte(0, CURRENT_VERSION);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you avoid these magic numbers and use constants or field size variables? or a relative setter? (set(dataLen))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

added CONSTANTS for the offsets.

}

@Override
protected void finalize() throws Throwable {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 on this, seems like its not something we should do lightly

how are you planning to solve it?

@@ -184,7 +192,23 @@ protected void setTransactionId(long txid) {
* @return payload of this log record.
*/
public byte[] getPayload() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why is this still necessary? back compat?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I kept it there for back compat.

@sijie
Copy link
Copy Markdown
Member Author

sijie commented Aug 30, 2017

@leighst : I address your comments. also removed the #finalize() approach.

  • LogRecord: copy the memory for reads, because we don't know how long the record will be held by the application, there is no simple way to release the reference
  • All the other classes - managing releasing the reference count.

Copy link
Copy Markdown

@eolivelli eolivelli left a comment

Choose a reason for hiding this comment

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

Great work @sijie

Copy link
Copy Markdown
Contributor

@leighst leighst left a comment

Choose a reason for hiding this comment

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

#shipit

@sijie
Copy link
Copy Markdown
Member Author

sijie commented Aug 31, 2017

FYI. the new compression codec shows much better result.

this patch:

Benchmark                                                                 (size)   Mode  Cnt      Score      Error   Units
CompressionBenchmark.testCompressLZ4                                          10  thrpt   50   6382.946 ±  252.338  ops/ms
CompressionBenchmark.testCompressLZ4                                         100  thrpt   50    560.667 ±   15.716  ops/ms
CompressionBenchmark.testCompressLZ4                                        1000  thrpt   50    198.630 ±    4.767  ops/ms
CompressionBenchmark.testCompressLZ4                                       10000  thrpt   50     61.814 ±    1.543  ops/ms
CompressionBenchmark.testCompressNone                                         10  thrpt   50  48918.275 ±  688.621  ops/ms
CompressionBenchmark.testCompressNone                                        100  thrpt   50  47937.500 ± 3246.851  ops/ms
CompressionBenchmark.testCompressNone                                       1000  thrpt   50  49029.124 ±  982.252  ops/ms
CompressionBenchmark.testCompressNone                                      10000  thrpt   50  50717.187 ± 1143.477  ops/ms
CompressionBenchmark.testDecompressLZ4                                        10  thrpt   50   7191.179 ±  196.163  ops/ms
CompressionBenchmark.testDecompressLZ4                                       100  thrpt   50   4435.242 ±   89.038  ops/ms
CompressionBenchmark.testDecompressLZ4                                      1000  thrpt   50    994.583 ±   22.731  ops/ms
CompressionBenchmark.testDecompressLZ4                                     10000  thrpt   50    112.235 ±    1.937  ops/ms
CompressionBenchmark.testDecompressNone                                       10  thrpt   50  36554.827 ±  571.760  ops/ms
CompressionBenchmark.testDecompressNone                                      100  thrpt   50  37407.131 ±  711.580  ops/ms
CompressionBenchmark.testDecompressNone                                     1000  thrpt   50  37218.008 ±  910.462  ops/ms
CompressionBenchmark.testDecompressNone                                    10000  thrpt   50  40611.669 ±  509.468  ops/ms

0.4.0-incubating

CompressionBenchmark.testCompressLZ4                                          10  thrpt   50    2422.408 ±   44.161  ops/ms
CompressionBenchmark.testCompressLZ4                                         100  thrpt   50    1793.394 ±   27.825  ops/ms
CompressionBenchmark.testCompressLZ4                                        1000  thrpt   50     928.596 ±   14.488  ops/ms
CompressionBenchmark.testCompressLZ4                                       10000  thrpt   50     239.443 ±    4.752  ops/ms
CompressionBenchmark.testCompressNone                                         10  thrpt   50  207570.657 ± 4656.234  ops/ms
CompressionBenchmark.testCompressNone                                        100  thrpt   50   90762.739 ± 1753.916  ops/ms
CompressionBenchmark.testCompressNone                                       1000  thrpt   50   10532.599 ±  207.739  ops/ms
CompressionBenchmark.testCompressNone                                      10000  thrpt   50    1034.792 ±   20.067  ops/ms
CompressionBenchmark.testDecompressLZ4                                        10  thrpt   50    4265.879 ±   80.825  ops/ms
CompressionBenchmark.testDecompressLZ4                                       100  thrpt   50    3975.214 ±  130.441  ops/ms
CompressionBenchmark.testDecompressLZ4                                      1000  thrpt   50    1821.820 ±   37.923  ops/ms
CompressionBenchmark.testDecompressLZ4                                     10000  thrpt   50     298.692 ±    8.591  ops/ms
CompressionBenchmark.testDecompressNone                                       10  thrpt   50  202194.272 ± 4431.166  ops/ms
CompressionBenchmark.testDecompressNone                                      100  thrpt   50   80907.829 ± 3869.202  ops/ms
CompressionBenchmark.testDecompressNone                                     1000  thrpt   50   10041.016 ±  391.215  ops/ms
CompressionBenchmark.testDecompressNone                                    10000  thrpt   50    1016.756 ±   26.645  ops/ms

@sijie sijie closed this in 46a3840 Aug 31, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants