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(...).