Class ByteSink
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 Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionbyte[]bytes()The backing array.voidensure(int extra) intlength()voidput(byte[] source, int offset, int count) voidput(int b) voidvoidASCII only, one byte per character.voidputCodePoint(int code) One code point as UTF-8.voidputNumber(long value) A number as ASCII digits, written in place.voidUTF-8, encoded in place.voidreset()
-
Constructor Details
-
ByteSink
public ByteSink(int initialCapacity)
-
-
Method Details
-
bytes
public byte[] bytes()The backing array. Valid up tolength; 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
-
putAscii
ASCII only, one byte per character. For header names, JSON punctuation and other text this code owns; anything from outside goes throughputUtf8(String). -
putUtf8
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.
-