This blog may seem obvious but its worth a mention anyway.
Low latency java needs to follow a different path from standard java and avoid allocations and unnecessary memcpy's.
Consider the following example, how many memory
allocations occur for the StringBuilder?
A) Typical java code
private
Message read() {
StringBuilder info = new StringBuilder();
Message m = decode();
info.append( "seqNum=" ).append( m.getSeqNum() )
.append( ", isDup="
).append( m.isPosDup() )
m.dump( info );
log( info );
return m;
}
GC .. who
cares ? Multiple allocs per call to read. Threadsafe
B)Presized string buffer
private
Message read() {
StringBuilderinfo = new StringBuilder(1024);
Message m = decode();
info.append( "seqNum=" ).append( m.getSeqNum() )
.append( ", isDup="
).append( m.isPosDup() )
m.dump( info );
log( info );
return m;
}
GC .. who
cares ? One buffer alloc per call to read. Threadsafe
C)Member variable
private final
StringBuilder _info = new StringBuilder();
private
Message read() {
_info.setLength(0);
Message m = decode();
_info.append( "seqNum=" ).append( m.getSeqNum() )
.append( ",
isDup=" ).append( m.isPosDup() )
m.dump( _info );
log( _info );
return m;
}
Lazy
initialisation for the StringBuilder. Some allocs until buffer hits max
required size.
Best option
where memory is limited and there can be many instances
Not thread
safe ... but thats FINE as all code assumed single threaded unless otherwise
specified
In ultra low
latency threading model is explicit and all contention minimised and
understood.
D)Presized member variable
private final
StringBuilder _info = new StringBuilder(1024);
private
Message read() {
_info.setLength(0);
Message m = decode();
if ( isLogEnabled() ) {
_info.append( "seqNum=" ).append( m.getSeqNum() )
.append( ",
isDup=" ).append( m.isPosDup() )
m.dump( _info );
log( _info );
}
return m;
}
Ok so the
guards should of been in all examples, but in typical java code its ignored and
the allocations and mempcy paid ... a lazy tax.
Ultra Low
Latency approach for the StringBuilder. Single buffer allocation presized to
max requirement.
Not thread
safe ... but thats FINE as all code assumed single threaded unless otherwise
specified
In ultra low
latency threading model is explicit and all contention minimised and
understood.
FYI
SubMicroTrading doesnt use StringBuilder but ReusableString to avoid the
overhead of toString() and uses byte instead of char.