On Wed, Dec 23, 2009 at 1:26 AM, Evan Jones <[email protected]> wrote:

> I've done some quick and dirty benchmarking of Java string encoding/
> decoding to/from UTF-8 for an unrelated project, but I've realized
> that these performance improvements could be added to protobufs. The
> "easy" way to do UTF-8 conversions is the way CodedInputStream/
> CodedOutputStream does it: using String.getBytes() and new String().
> It turns out that using the java.nio.charset.CharsetDecoder/
> CharsetEncoder *can* be faster. However, to make it faster the objects
> need to be reused, due to the cost of allocating temporary buffers and
> objects.
>
> Before I attempt to make any improvements, I want to see if anyone
> (Kenton primarily) has any opinions if these make sense. They would
> add ~100 lines of code to replace something which is now a few lines
> of code, and it is a small improvement (approximately 40% less time
> per encode/decode, on a list of 1400 strings in different languages).
> I haven't tried adding this to protobufs yet, so final performance
> improvements are unknown:
>
>
> Problem 1: A Java protobuf string is stored as a String instance. It
> typically gets converted to UTF-8 *twice*: Once in getSerializedSize()
> via a call to CodedOutputStream.computeStringSize, then again in
> writeTo().
>
> Solution: Cache the byte[] version of String fields. This would
> increase the memory size of each message (an additional pointer per
> string, plus the space for the byte[]), but would HALVE the number of
> conversions. I suspect this will be a fair bit faster. If added, it
> should only be added for the SPEED generated messages.
>

I noticed this as well before ... the solution could be applied to *all*
generated messages for efficiency.
There should be a writeByteArray(int fieldNumber, byte[] value) in
CodedOutputStream so that the cached bytes of strings would
be written directly.  The ByteString would not help, it adds more memory
since it creates a copy of the byte array.


>
> Problem 2: Using the NIO encoders/decoders can be faster than
> String.getBytes, but only if it is used >= 4 times. If used only once,
> it is worse. The same is approximately true about decoding. Lame
> results: http://evanjones.ca/software/java-string-encoding.html
>
> Solution 1: Add a custom encoder/decoder to CodedOutputStream,
> allocated as needed. This could be *bad* for applications that call
> Message.toByteString or .toByteArray frequently for messages with few
> strings, since that creates and throws away a single CodedOutputStream
> instance.
>
> Solution 2: Add a custom encoder/decoder per thread via a ThreadLocal.
> This requires fetching the ThreadLocal, which is slightly expensive,
> and adds some per-thread memory overhead (~ 4kB, tunable). however the
> allocations are done ONCE per thread, which should be significantly
> better.
>
>
> --
> Evan Jones
> http://evanjones.ca/
>
> --
>
> You received this message because you are subscribed to the Google Groups
> "Protocol Buffers" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected]<protobuf%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/protobuf?hl=en.
>
>
>


-- 
When the cat is away, the mouse is alone.
- David Yu

--

You received this message because you are subscribed to the Google Groups 
"Protocol Buffers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en.


Reply via email to