netty/netty — pull request #2865 by normanmaurer (2014-09-04 14:13:10+00:00)
Title: Provide helper methods in ByteBufUtil to write UTF-8/ASCII CharSequences...

.... Related to [#909]

Motivation:

We expose no methods in ByteBuf to directly write a CharSequence into it. This leads to have the user either convert the CharSequence first to a byte array or use CharsetEncoder. Both cases have some overheads and we can do a lot better for well known Charsets like UTF-8 and ASCII.

Modifications:

Add ByteBufUtil.writeAsciiCharSequence(...) and ByteBufUtil.writeUtf8CharSequence(...) which can do the task in an optimized way. This is especially true if the passed in ByteBuf extends AbstractByteBuf which is true for all of our implementations which not wrap another ByteBuf.

Result:

Writing an ASCII and UTF-8 CharSequence into a AbstractByteBuf is a lot faster then what the user could do by himself as we can make use of some package private methods and so eliminate reference and range checks. When the Charseq is not ASCII or UTF-8 we can still do a very good job and are on par in most of the cases with what the user would do.

The following bechmark shows the improvements:

Benchmark Mode Samples Score Score error Units
i.n.m.b.ByteBufUtilBenchmark.writeAsciiCharSequence thrpt 50 9071736,721 587948,771 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeAsciiCharSequenceViaArray thrpt 50 3043807,652 208008,698 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeAsciiCharSequenceViaArrayWrapped thrpt 50 3024189,530 198905,388 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeAsciiCharSequenceWrapped thrpt 50 3409030,169 91543,588 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeAsciiString thrpt 50 10089151,297 286351,733 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeAsciiStringViaArray thrpt 50 4906278,232 172291,820 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeAsciiStringViaArrayWrapped thrpt 50 4511319,426 280382,742 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeAsciiStringWrapped thrpt 50 4458570,751 227097,569 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeUtf8CharSequence thrpt 50 9847334,965 515519,775 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeUtf8CharSequenceViaArray thrpt 50 3321834,254 119002,597 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeUtf8CharSequenceViaArrayWrapped thrpt 50 3143624,224 148331,202 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeUtf8CharSequenceWrapped thrpt 50 3442477,836 98653,095 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeUtf8String thrpt 50 9571479,473 582890,330 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeUtf8StringViaArray thrpt 50 3639893,464 84165,504 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeUtf8StringViaArrayWrapped thrpt 50 3613282,539 95278,392 ops/s
i.n.m.b.ByteBufUtilBenchmark.writeUtf8StringWrapped thrpt 50 3424367,302 167819,611 ops/s
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1,370.56 sec - in io.netty.microbench.buffer.ByteBufUtilBenchmark

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

The *ViaArray* benchmarks are basically doing a toString().getBytes(Charset) which the others are using ByteBufUtil.write*CharSequence(...).