In This Section
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.
XString ADM Accessors
ADM generated messages and entities provide specialized setters and getters for String fields that accept an XString which allows zero garbage operation. The following tables list String related accessors for a field named XXX, and highlights whether or not the accessor is zerog garbage when using Xbuf encoding.
Getters | Description | Zero Garbage |
---|---|---|
String getXXX() | Returns the field value as a String. | No |
String getXXX(String defaultIfNotSet) | Returns the field value as a String, or the provided value if the field is not set. | No |
XString getXXXUnsafe() | Returns the raw XString which may be pooled along with the message and point to its backing buffer.
| Yes |
XString getXXXUnsafe(XString defaultIfNotSet) | Returns the getXXXUnsafe() or the provided XString if the field is not set. The same restrctions that apply to XString getXXXUnsafe() apply here, too. | Yes |
void getXXXTo(XString to) | Copying accessor. Copies the value of the field into the provided XString. This method is a safer alternative to getXXXUnsafe as the copied value is safe to retain beyond thepooling lifespan of the object. | Yes |
void getXXXTo(XString to, XString defaultIfNotSet) | Copying accessor. This is equivalent to getXXXTo(XString to), but if the field is not set the default value is copied into the provided value. | Yes |
<T extends XString> T getXXXTo(XString.Factory<T> factory) | Copying accessor. Similar to getXXXTo, but draws the value to copy into from the provided XString factory. This method is useful when working with a string field that is declared as poolable. This allows the application to preallocate a pool of XStrings to draw upon when copying string fields from a message | Yes |
<T extends XString> T getXXXTo(XString.Factory<T>factory, T defaultIfNotSet) | Copying accessor. Similar to getXXXTo(factory), but will copy in the provided default value if the field is not set on the object. | Yes |
Setters | Description | |
void setXXX(String val) | Sets the value of the field | Yes |
void setXXXFrom(long val) | Encodes the provider long value as a decimal string. | Yes |
void setXXXFrom(XString val) | Copying setter. This method copies the provided value into the object. This method can be more efficient than the setXXX(String) as it can copy the provided value's backing buffer directly. | Yes |
void lendXXX(XString) | This method is equivalent to setXXX except that it allows this object to defer copying the value until this object is next serialized.
| Yes |
See also: XBuf - Repeated Field Bulk Copies