[CASSANDRA-21528] Cache Enum.values() in ClusteringPrefix.Kind deserialization to avoid per-read array allocation

This commit is contained in:
koo.taejin 2026-07-24 21:49:50 +09:00
parent 1a51fdae2c
commit f9438f8cd5
12 changed files with 81 additions and 21 deletions

View File

@ -96,12 +96,19 @@ public abstract class Selector
SLICE_SELECTOR(ElementsSelector.SliceSelector.deserializer),
VECTOR_SELECTOR(VectorSelector.deserializer);
private static final Kind[] VALUES = values();
private final SelectorDeserializer deserializer;
Kind(SelectorDeserializer deserializer)
{
this.deserializer = deserializer;
}
public static Kind fromOrdinal(int ordinal)
{
return VALUES[ordinal];
}
}
/**
@ -260,7 +267,7 @@ public abstract class Selector
public Selector deserialize(DataInputPlus in, int version, TableMetadata metadata) throws IOException
{
Kind kind = Kind.values()[in.readUnsignedByte()];
Kind kind = Kind.fromOrdinal(in.readUnsignedByte());
return kind.deserializer.deserialize(in, version, metadata);
}

View File

@ -116,7 +116,7 @@ public interface ClusteringBoundOrBoundary<V> extends ClusteringPrefix<V>
public ClusteringBoundOrBoundary<byte[]> deserialize(DataInputPlus in, int version, List<AbstractType<?>> types) throws IOException
{
Kind kind = Kind.values()[in.readByte()];
Kind kind = Kind.fromOrdinal(in.readByte());
return deserializeValues(in, kind, version, types);
}

View File

@ -84,6 +84,8 @@ public interface ClusteringPrefix<V> extends IMeasurableMemory, Clusterable<V>
SSTABLE_UPPER_BOUND ( 4, 1, v -> ByteSource.GTGT_NEXT_COMPONENT);
// @formatter:on
private static final Kind[] VALUES = values();
private final int comparison;
/**
@ -101,6 +103,11 @@ public interface ClusteringPrefix<V> extends IMeasurableMemory, Clusterable<V>
this.asByteComparable = asByteComparable;
}
public static Kind fromOrdinal(int ordinal)
{
return VALUES[ordinal];
}
/**
* Compares the 2 provided kind.
* <p>
@ -476,7 +483,7 @@ public interface ClusteringPrefix<V> extends IMeasurableMemory, Clusterable<V>
public void skip(DataInputPlus in, int version, List<AbstractType<?>> types) throws IOException
{
Kind kind = Kind.values()[in.readByte()];
Kind kind = Kind.fromOrdinal(in.readByte());
// We shouldn't serialize static clusterings
assert kind != Kind.STATIC_CLUSTERING;
if (kind == Kind.CLUSTERING)
@ -487,7 +494,7 @@ public interface ClusteringPrefix<V> extends IMeasurableMemory, Clusterable<V>
public ClusteringPrefix<byte[]> deserialize(DataInputPlus in, int version, List<AbstractType<?>> types) throws IOException
{
Kind kind = Kind.values()[in.readByte()];
Kind kind = Kind.fromOrdinal(in.readByte());
// We shouldn't serialize static clusterings
assert kind != Kind.STATIC_CLUSTERING;
if (kind == Kind.CLUSTERING)
@ -631,8 +638,6 @@ public interface ClusteringPrefix<V> extends IMeasurableMemory, Clusterable<V>
*/
public static class Deserializer
{
private static final ClusteringPrefix.Kind[] KINDS = ClusteringPrefix.Kind.values();
private final ClusteringComparator comparator;
private final DataInputPlus in;
private final SerializationHeader serializationHeader;
@ -659,7 +664,7 @@ public interface ClusteringPrefix<V> extends IMeasurableMemory, Clusterable<V>
throw new IOException("Corrupt flags value for clustering prefix (isStatic flag set): " + flags);
this.nextIsRow = UnfilteredSerializer.kind(flags) == Unfiltered.Kind.ROW;
this.nextKind = nextIsRow ? Kind.CLUSTERING : KINDS[in.readByte()];
this.nextKind = nextIsRow ? Kind.CLUSTERING : Kind.fromOrdinal(in.readByte());
this.nextSize = nextIsRow ? comparator.size() : in.readUnsignedShort();
this.deserializedSize = 0;

View File

@ -198,6 +198,8 @@ public abstract class ReadCommand extends AbstractReadQuery
SINGLE_PARTITION (SinglePartitionReadCommand.selectionDeserializer, SinglePartitionReadCommand.accordSelectionDeserializer),
PARTITION_RANGE (PartitionRangeReadCommand.selectionDeserializer, ignore -> PartitionRangeReadCommand.selectionDeserializer);
private static final Kind[] VALUES = values();
private final SelectionDeserializer selectionDeserializer;
private final Function<Seekable, SelectionDeserializer> accordSelectionDeserializer;
@ -206,6 +208,11 @@ public abstract class ReadCommand extends AbstractReadQuery
this.selectionDeserializer = selectionDeserializer;
this.accordSelectionDeserializer = accordSelectionDeserializer;
}
public static Kind fromOrdinal(int ordinal)
{
return VALUES[ordinal];
}
}
protected ReadCommand(Epoch serializedAtEpoch,
@ -1450,7 +1457,7 @@ public abstract class ReadCommand extends AbstractReadQuery
public ReadCommand deserialize(DataInputPlus in, int version) throws IOException
{
Kind kind = Kind.values()[in.readByte()];
Kind kind = Kind.fromOrdinal(in.readByte());
int flags = in.readByte();
// Shouldn't happen or it's a user error (see comment above) but
// better complain loudly than doing the wrong thing.
@ -1488,7 +1495,7 @@ public abstract class ReadCommand extends AbstractReadQuery
public ReadCommand deserializeForAccord(Seekable key, TableMetadatas tables, DataInputPlus in, int version) throws IOException
{
Kind kind = Kind.values()[in.readByte()];
Kind kind = Kind.fromOrdinal(in.readByte());
int flags = in.readByte();
if (isDigest(flags) || isForThrift(flags) || acceptsTransient(flags))
throw new IllegalStateException("Received an Accord command with a digest/thrift/transient flag set.");

View File

@ -65,7 +65,14 @@ public abstract class AggregationSpecification
*/
public enum Kind
{
AGGREGATE_EVERYTHING, AGGREGATE_BY_PK_PREFIX, AGGREGATE_BY_PK_PREFIX_WITH_SELECTOR
AGGREGATE_EVERYTHING, AGGREGATE_BY_PK_PREFIX, AGGREGATE_BY_PK_PREFIX_WITH_SELECTOR;
private static final Kind[] VALUES = values();
public static Kind fromOrdinal(int ordinal)
{
return VALUES[ordinal];
}
}
/**
@ -253,7 +260,7 @@ public abstract class AggregationSpecification
public AggregationSpecification deserialize(DataInputPlus in, int version, TableMetadata metadata) throws IOException
{
Kind kind = Kind.values()[in.readUnsignedByte()];
Kind kind = Kind.fromOrdinal(in.readUnsignedByte());
switch (kind)
{
case AGGREGATE_EVERYTHING:

View File

@ -80,7 +80,7 @@ public abstract class AbstractClusteringIndexFilter implements ClusteringIndexFi
public ClusteringIndexFilter deserialize(DataInputPlus in, int version, TableMetadata metadata) throws IOException
{
Kind kind = Kind.values()[in.readUnsignedByte()];
Kind kind = Kind.fromOrdinal(in.readUnsignedByte());
boolean reversed = in.readBoolean();
return kind.deserializer.deserialize(in, version, metadata, reversed);

View File

@ -46,12 +46,19 @@ public interface ClusteringIndexFilter
SLICE (ClusteringIndexSliceFilter.deserializer),
NAMES (ClusteringIndexNamesFilter.deserializer);
private static final Kind[] VALUES = values();
protected final InternalDeserializer deserializer;
private Kind(InternalDeserializer deserializer)
{
this.deserializer = deserializer;
}
public static Kind fromOrdinal(int ordinal)
{
return VALUES[ordinal];
}
}
static interface InternalDeserializer

View File

@ -44,7 +44,17 @@ public abstract class ColumnSubselection implements Comparable<ColumnSubselectio
public static final Serializer serializer = new Serializer();
/* this enum is used in serialization; preserve order for compatibility */
private enum Kind { SLICE, ELEMENT }
private enum Kind
{
SLICE, ELEMENT;
private static final Kind[] VALUES = values();
static Kind fromOrdinal(int ordinal)
{
return VALUES[ordinal];
}
}
protected final ColumnMetadata column;
@ -229,7 +239,7 @@ public abstract class ColumnSubselection implements Comparable<ColumnSubselectio
}
}
Kind kind = Kind.values()[in.readUnsignedByte()];
Kind kind = Kind.fromOrdinal(in.readUnsignedByte());
switch (kind)
{
case SLICE:

View File

@ -102,7 +102,14 @@ public abstract class DataLimits
/** @deprecated See CASSANDRA-16582 */
@Deprecated(since = "4.0") SUPER_COLUMN_COUNTING_LIMIT, //Deprecated and unused in 4.0, stop publishing in 5.0, reclaim in 6.0
CQL_GROUP_BY_LIMIT,
CQL_GROUP_BY_PAGING_LIMIT,
CQL_GROUP_BY_PAGING_LIMIT;
private static final Kind[] VALUES = values();
public static Kind fromOrdinal(int ordinal)
{
return VALUES[ordinal];
}
}
public static DataLimits cqlLimits(int cqlRowLimit)
@ -1191,7 +1198,7 @@ public abstract class DataLimits
public DataLimits deserialize(DataInputPlus in, int version, TableMetadata metadata) throws IOException
{
Kind kind = Kind.values()[in.readUnsignedByte()];
Kind kind = Kind.fromOrdinal(in.readUnsignedByte());
switch (kind)
{
case CQL_LIMIT:

View File

@ -493,7 +493,17 @@ public class RowFilter implements Iterable<RowFilter.Expression>
// and this is why we have some UNUSEDX for values we don't use anymore
// (we could clean those on a major protocol update, but it's not worth
// the trouble for now)
protected enum Kind { SIMPLE, MAP_ELEMENT, UNUSED1, CUSTOM, USER }
protected enum Kind
{
SIMPLE, MAP_ELEMENT, UNUSED1, CUSTOM, USER;
private static final Kind[] VALUES = values();
static Kind fromOrdinal(int ordinal)
{
return VALUES[ordinal];
}
}
protected abstract Kind kind();
protected final ColumnMetadata column;
@ -685,7 +695,7 @@ public class RowFilter implements Iterable<RowFilter.Expression>
public Expression deserialize(DataInputPlus in, int version, TableMetadata metadata) throws IOException
{
Kind kind = Kind.values()[in.readByte()];
Kind kind = Kind.fromOrdinal(in.readByte());
// custom expressions (3.0+ only) do not contain a column or operator, only a value
if (kind == Kind.CUSTOM)

View File

@ -61,7 +61,7 @@ public class ClusteringDescriptor extends ResizableByteBuffer
protected void loadClustering(RandomAccessReader dataReader, byte clusteringKind, int clusteringColumnsBound) throws IOException
{
set(ClusteringPrefix.Kind.values()[clusteringKind], clusteringKind, clusteringColumnsBound);
set(ClusteringPrefix.Kind.fromOrdinal(clusteringKind), clusteringKind, clusteringColumnsBound);
if (clusteringKind != STATIC_CLUSTERING_KIND)
readUnfilteredClustering(dataReader, clusteringTypes, this.clusteringColumnsBound, this);
else
@ -103,7 +103,7 @@ public class ClusteringDescriptor extends ResizableByteBuffer
}
private void set(byte clusteringKindEncoded, int clusteringColumnsBound) {
set(ClusteringPrefix.Kind.values()[clusteringKindEncoded], clusteringKindEncoded, clusteringColumnsBound);
set(ClusteringPrefix.Kind.fromOrdinal(clusteringKindEncoded), clusteringKindEncoded, clusteringColumnsBound);
}
private void set(ClusteringPrefix.Kind clusteringKind, byte clusteringKindEncoded, int clusteringColumnsBound)

View File

@ -513,7 +513,7 @@ public class SSTableCursorWriter implements AutoCloseable
public void writeRangeTombstone(UnfilteredDescriptor rangeTombstone, boolean updateClusteringMetadata) throws IOException
{
int tombstoneKind = rangeTombstone.clusteringKindEncoded();
ClusteringPrefix.Kind kind = ClusteringPrefix.Kind.values()[tombstoneKind];
ClusteringPrefix.Kind kind = ClusteringPrefix.Kind.fromOrdinal(tombstoneKind);
long unfilteredStartPosition = getPosition();
/** See: {@link org.apache.cassandra.db.rows.UnfilteredSerializer#serialize */
dataWriter.writeByte((byte)IS_MARKER);