I think Martin explained the reasoning quite well in his talk High
Performance Managed Languages
<https://www.infoq.com/presentations/performance-managed-languages>

On Wed, Jul 19, 2017 at 10:28 AM, Avi Kivity <a...@scylladb.com> wrote:

> Out of curiosity, if you're doing heavy duty processing, why did you
> choose a garbage-collected language?
>
> On 07/19/2017 04:21 AM, David Ryan wrote:
>
>
> Hi all,
>
> My first post here.  Not sure it's the best place for it, but hoping
> someone here might be able to assist.  We're developers of a streaming
> application that does 100k+ messages per second processing, so anything
> that allocates to the heap can cause GC pressure.  We've been targeting
> removing allocations recently and one difficult ones is conversion from
> String to UTF-8 to OutputStream.  The advised methods for String to UTF-8
> all create byte[] as intermediary objects.
>
> We've been able to read Strings from streams using a ThreadLocal
> ByteBuffer and CharBuffer which will allocate the char[] and String object
> only.  For reference, we've done the following.  In a 1minute JMC Flight
> Recorder char[] and String make up about 1 gig or allocations which is
> unavoidable because we're processing a lot of string data:
>
>     public static final class StringBuffers
>     {
>         ByteBuffer buffer = ByteBuffer.allocate(512);
>         CharBuffer charBuffer = CharBuffer.allocate(300);
>         CharsetDecoder decoder = Charset.forName("UTF8").newDecoder();
>     }
>
>     public static final class U8Utf8MethodHandleReader extends
> AbstractReader
>     {
>         private final ThreadLocal<StringBuffers> buffers = new
> ThreadLocal<StringBuffers>()
>         {
>             @Override
>             public StringBuffers initialValue()
>             {
>                 return new StringBuffers();
>             }
>         };
>
>         public U8Utf8MethodHandleReader(final MethodHandle setHandle)
>         {
>             super(setHandle);
>         }
>
>         @Override
>         public void read(final Object o, final TypeInputStream in) throws
> Throwable
>         {
>             final int len = in.read();
>
>             // Grab a thread local set of buffers to use temporarily.
>             final StringBuffers buf = buffers.get();
>
>             // get a reference to the buffers.
>             final ByteBuffer b = buf.buffer;
>             final CharBuffer c = buf.charBuffer;
>
>             b.clear();
>             c.clear();
>
>             // read the stream into the byte buffer.
>             in.getStream().read(b.array(), 0, len);
>             b.limit(len);
>
>             // decode the bytes into the char buffer.
>             final CharsetDecoder decoder = buf.decoder;
>             decoder.reset();
>             decoder.decode(b, c, true);
>
>             // flip the char buffer.
>             c.flip();
>
>             // get a copy of
>             final String str = c.toString();
>
>             // finally set the string value via method handle.
>             setHandle.invoke(o, str);
>         }
>     }
>
> For writing Strings we've tried a similar method:
>
>     public static final class StringBuffers
>     {
>         ByteBuffer buffer = ByteBuffer.allocate(512);
>         CharsetEncoder encoder = Charset.forName("UTF8").newEncoder();
>     }
>
>     public static final class U8Utf8MethodHandleWriter extends
> AbstractWriter
>     {
>         private final ThreadLocal<StringBuffers> buffers = new
> ThreadLocal<StringBuffers>()
>         {
>             @Override
>             public StringBuffers initialValue()
>             {
>                 return new StringBuffers();
>             }
>         };
>
>         public U8Utf8MethodHandleWriter(final MethodHandle getHandle)
>         {
>             super(getHandle);
>         }
>
>         @Override
>         public void write(final Object o, final TypeOutputStream out)
> throws Throwable
>         {
>             // finally set the string value.
>             final String str = (String) getHandle.invoke(o);
>
>             final OutputStream os = out.getStream();
>
>             // empty strings just write 0 for length.
>             if (str == null)
>             {
>                 os.write(0);
>                 return;
>             }
>
>             // Grab a thread local set of buffers to use temporarily.
>             final StringBuffers buf = buffers.get();
>
>             // get a reference to the buffers.
>             final ByteBuffer b = buf.buffer;
>
>             // this does allocate an object, but at least it isn't copying
> the buffer!
>             final CharBuffer c = CharBuffer.wrap(str);
>
>             // clear the byte buffer.
>             b.clear();
>
>             // decode the bytes into the char buffer.
>             final CharsetEncoder encoder = buf.encoder;
>             encoder.reset();
>             encoder.encode(c, b, true);
>
>             // flip the char buffer.
>             b.flip();
>
>             final int size = b.limit();
>
>             if (size > 255)
>             {
>                 throw new TypeException("u8ascii: String length exceeded
> max length of 255.  len =" + size);
>             }
>
>             if (writeNotNull)
>             {
>                 os.write(1);
>             }
>
>             os.write(size);
>             os.write(b.array(), 0, size);
>         }
>     }
>
> The offending CharBuffer.wrap(str) currently allocates 766MB in a one
> minute period and has the largest allocation profile for the application.
>
> Interested if anyone else has found a better solution for this or can
> suggest alternative solutions.
>
> Thanks,
> David.
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to mechanical-sympathy+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to mechanical-sympathy+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to