mirror of https://github.com/apache/cassandra
Description:
AbstractType.writeValue() is one shared method. All column types use it.
Inside writeValue(), it calls valueLengthIfFixed(). This is a virtual call. Many types override this method (Int32Type, LongType, UTF8Type, ...).
In a real cluster, many column types pass through writeValue(). So the profile always sees lots types.
Because of this, the JIT cannot inline the call. It stays as a vtable call. Also, the compiled body of writeValue() becomes big, so the JIT refuses to inline writeValue() itself ("already compiled into a big method").
We also see the same itable/vtable stubs in async-profiler output from a real cluster, running with default production options and a normal workload.
How to solve:
Add a final int field to AbstractType. Set it in the constructor. writeValue() reads this field instead of calling valueLengthIfFixed().
A field read needs no type profile. So profile pollution has no effect on it. The valueLengthIfFixed() method is not changed. Only the write path uses the field.
Result:
Production is always the polluted state, so this is the real-world comparison
JMH, JDK 17 / arm64, 1 thread, 10 x 1s warmup and measurement:
before after improvement
readValue 49.99M ops/s 56.44M ops/s +12.90%
writeValue 99.63M ops/s 114.46M ops/s +14.88%
patch by Koo Taejin; reviewed by Dmitry Konstantinov, Francisco Guerrero for CASSANDRA-21536
|
||
|---|---|---|
| .. | ||
| com/datastax/driver/core | ||
| org | ||