You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by "Stefan Miklosovic (Jira)" <ji...@apache.org> on 2026/07/24 09:31:00 UTC
[jira] [Comment Edited] (CASSANDRA-21528) Cache Enum.values() in ClusteringPrefix.Kind deserialization to avoid per-read array allocation
[ https://issues.apache.org/jira/browse/CASSANDRA-21528?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18098825#comment-18098825 ]
Stefan Miklosovic edited comment on CASSANDRA-21528 at 7/24/26 9:30 AM:
------------------------------------------------------------------------
||File:line||Path||Frequency||
|{{ClusteringPrefix.java:479, 490, 660}}|clustering/bound deserialize|*per clustering prefix* (the ticket itself)|
|{{io/sstable/ClusteringDescriptor.java:64, 106}}|SSTable cursor read|*per clustering read from disk*|
|{{io/sstable/SSTableCursorWriter.java:516}}|SSTable write|*per tombstone marker* (flush/compaction)|
|{{db/ClusteringBoundOrBoundary.java:119}}|range-bound deserialize|*per range-tombstone bound*|
Recommended fix (covers all 4): add to ClusteringPrefix.Kind:
{code}
public enum Kind {
...
private static final Kind[] VALUES = values(); // cache; never mutate, never expose
public static Kind fromOrdinal(int i) { return VALUES[i]; }
}
{code}
was (Author: smiklosovic):
||File:line||Path||Frequency||
|{{ClusteringPrefix.java:479, 490, 660}}|clustering/bound deserialize|*per clustering prefix* (the ticket itself)|
|{{io/sstable/ClusteringDescriptor.java:64, 106}}|SSTable cursor read|*per clustering read from disk*|
|{{io/sstable/SSTableCursorWriter.java:516}}|SSTable write|*per tombstone marker* (flush/compaction)|
|{{db/ClusteringBoundOrBoundary.java:119}}|range-bound deserialize|*per range-tombstone bound*|
> Cache Enum.values() in ClusteringPrefix.Kind deserialization to avoid per-read array allocation
> -----------------------------------------------------------------------------------------------
>
> Key: CASSANDRA-21528
> URL: https://issues.apache.org/jira/browse/CASSANDRA-21528
> Project: Apache Cassandra
> Issue Type: Improvement
> Components: Legacy/Core
> Reporter: koo
> Assignee: koo
> Priority: Normal
> Fix For: 6.x, 7.x
>
> Time Spent: 10m
> Remaining Estimate: 0h
>
> *description*
> When deserializing clusterings and range/slice bounds, the kind is resolved via Kind.values()[in.readByte()]:
> - ClusteringPrefix.java:616 — ClusteringPrefix.Deserializer (streaming path) // 5.0.7
>
> Enum.values() creates a new copy of its array every time it is called. So each time we read a clustering or a bound, a new Kind[] array is created just to look up one value by index, and then thrown away. This runs on the hot deserialization path, so it creates a lot of short-lived garbage for no real benefit.
>
> Impact (measured, JFR allocation profiling on a read/Paxos-LWT-heavy workload):
> - Total heap allocation observed: ~170 GB (120s)
> - ClusteringPrefix$Kind[]: ~5.22 GB (≈3.1%) of that total
> This garbage is short-lived, so GC pause impact under a modern collector is minimal and CPU cost is negligible; this is purely an allocation-pressure / GC-throughput improvement.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org