Class ByteSink

java.lang.Object
com.codename1.backend.ByteSink

public final class ByteSink extends Object

A growable byte buffer that callers reuse.

This exists because building output as a String and then encoding it is the single most expensive thing a server can do per request. Measured on this server: the response head alone, built with a StringBuilder, turned into a String and then into bytes, was a third of all allocation; the JSON body was most of the rest. Written as bytes into a buffer that lives as long as the connection, both cost nothing.

Deliberately not java.io.ByteArrayOutputStream: that one cannot be reset without discarding its buffer on some implementations, has synchronized methods, and hands out a COPY of its contents -- three allocations where this has none.

Not thread safe. One per connection, used by the worker that owns it.

  • Constructor Details

    • ByteSink

      public ByteSink(int initialCapacity)
  • Method Details

    • bytes

      public byte[] bytes()
      The backing array. Valid up to length; not a copy.
    • length

      public int length()
    • reset

      public void reset()
    • ensure

      public void ensure(int extra)
    • put

      public void put(int b)
    • put

      public void put(byte[] source, int offset, int count)
    • put

      public void put(ByteSink other)
    • putAscii

      public void putAscii(String ascii)
      ASCII only, one byte per character. For header names, JSON punctuation and other text this code owns; anything from outside goes through putUtf8(String).
    • putUtf8

      public void putUtf8(String value)

      UTF-8, encoded in place.

      String.getBytes("UTF-8") would allocate the array this exists to avoid, and on the translated target it goes through the platform's encoder for every call. Surrogate pairs are combined; an unpaired surrogate becomes U+FFFD, because emitting a lone surrogate produces bytes no decoder will accept.

    • putCodePoint

      public void putCodePoint(int code)

      One code point as UTF-8.

      Separate from putUtf8(String) because a caller walking a String character by character has to combine a surrogate PAIR itself -- handing the halves over one at a time turns an emoji into two replacement characters, which is what the JSON writer did until its output was compared against the String form byte for byte.

    • putNumber

      public void putNumber(long value)
      A number as ASCII digits, written in place. Long.toString would allocate a String and its char[], and this is on the path of every response (the status and the content length) and every JSON number.