What is an XString?
Java Strings pose challenges for ultra low latency applications looking to achieve zero garbage. Because java.lang.Strings are immutable they are not conducive to pooling and preallocation, and encoding and decoding of String can be cpu intensive. Consequently, Talon provides an alternate implementation, XString. An XString wraps an encoded set of bytes representing a string. An XString
provides the ability to manipulate String values without generating the garbage associated with Java's String
implementation. An XString is often referred to as a 'RawString' which is a historical moniker that reflects XString raw access to the String underlying serialized byte form.
This class serves the following purposes:
Zero Garbage Preallocation
If a String
needs to be maintained in memory for a long period of time as part of an application's state, late allocation of the String
would normally produce an object that generational garbage collection would have to promote into tenured memory. For latency sensitive application's promotion of the String to the tenured generation will leads to garbage collection pauses. A XString
allows preallocation of memory for such a field up front whereas a String can't be preallocated because it is immutable.
An XString
may be preallocated via one of its factory methods or via the factory methods for XString in XFactory
. The XString
and its backing buffer will be promoted to the tenured generation at the beginning of the application's life cycle allowing the tenuring cost to be paid up front thereby eliminating pauses that would result from minor gc during normal application operation.
When the XString
is later assigned from another XString
, the backing buffer can be copied from it without any garbage being created. A typical example of this would be where a transport layer reads a field off the wire and passes it off to the application. The networking layer wraps the encoded buffer in a pooled XString
and can pass it off to application code that has a preallocated XString
that serves as the target. The network buffer is copied into the preallocated target without instantiating the underlying non primitive type meaning that no garbage is created in the course of setting the field.
However even if the underlying value is materialized by application code via a call to getValue()
, the cost in garbage can remain low providing the application doesn't keep a reference to the materialized value because because the materialized value needn't be promoted to an eden survivor space or the tenured generation which is the more expensive operation in garbage collection. The application keeps a reference to the XString
only and can continue to transiently decode the value and release it as needed.
Zero Copy/Reencode Serializable Field Transfer
In the case where a value needs to be transfered from one serializable object to another, an XString allows the transfer of the field without costly character decoding or reencoding the value. For latency sensitive application this is important for two reasons. Firstly, decoding to a String
introduces intermediate garbage in the form of the materialized value returned by getValue()
, and secondly the decode/encode operation costs clock cycles.
As alluded to above, for a networking application that reuses its network buffers, a XString
can be layered on top of a network buffer and presented to the application which can pass the XString
to an outbound network buffer where it can be written without (de)serialization and (re)encoding. When the backing buffer is a direct or native buffer this provides a mechanism for field transfer with zero intermediate copy.
Immutability of XString
An immutable XString
created via one of the factory methods of XFactory
is immutable from the point that it is initialized. Once initialized via a setter method, a factory created XString
is threadsafe.
However, not all XString
s are threadsafe or immutable: platform created XString
may not always be immutable. Applications can test for immutability and initialization of a XString
via isImmutable()
and isInitialized()
. When dealing with XString
s returned by platform classes the documentation of the class should be consulted to determine what thread safety and immutability guarantees are provided. In cases where the platform doesn't guaranteed immutability, applications can make use of copyInto(XString)
to create an immutable version of the XString
if needs be.
Character Encoding
For interoperability XString implements Appendable
and CharSequence
. Currently XString
only supports ascii encdodable characters when working with these interfaces, or any of the other char based methods it supports. An XString
can opaquely wrap and and pass non ascii encodabled XStrings, but for performance reasons direct character manipulation of non ascii text is not supported.
CharSequence view
XString implements CharSequence
. The hashCode()
and equals(Object)
implementations of this view and those returned by subSequence(int, int)
are not guaranteed to be remain stable when an XString is mutable or not yet initialized.
Equality and hashCode
XString
s that are immutable obey the contract for object equality and hashCode. Additionally, an XString will equal another XString.subSequence(int, int)
if they have the same value. An XString
will not equal another String
of the same value.