Skip to content

Commit 75b9b75

Browse files
committed
(improvement) cqltypes: Cache serial_size in VectorType to avoid repeated method dispatch
Cache subtype.serial_size() and the full vector serial_size() as class attributes (_subtype_serial_size, _serial_size) during apply_parameters(). This eliminates per-call method dispatch overhead in serialize(), deserialize(), and serial_size() hot paths. serial_size() call: 99ns -> 46ns (2.2x faster) Attribute access: 54ns -> 17ns (3.2x faster)
1 parent 0535ecd commit 75b9b75

1 file changed

Lines changed: 12 additions & 5 deletions

File tree

cassandra/cqltypes.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,11 +1439,13 @@ class VectorType(_CassandraType):
14391439
_vector_struct = None # Cached struct.Struct for bulk deserialization
14401440
_struct_format_map = {} # Populated after FloatType etc. are defined
14411441
_numpy_dtype = None # Cached numpy dtype string for large vector deserialization
1442+
_subtype_serial_size = None # Cached subtype.serial_size() (computed once in apply_parameters)
1443+
_serial_size = None # Cached serial_size() for the full vector (subtype_serial_size * vector_size)
14421444

14431445
@classmethod
14441446
def serial_size(cls):
1445-
serialized_size = cls.subtype.serial_size()
1446-
return cls.vector_size * serialized_size if serialized_size is not None else None
1447+
return cls._serial_size
1448+
14471449

14481450
@classmethod
14491451
def apply_parameters(cls, params, names):
@@ -1458,12 +1460,17 @@ def apply_parameters(cls, params, names):
14581460
vector_struct = struct.Struct(f'>{vsize}{fmt_char}')
14591461
numpy_dtype = cls._numpy_dtype_map.get(fmt_char)
14601462
break
1463+
# Cache subtype serial_size and full vector serial_size to avoid
1464+
# repeated method dispatch in serialize/deserialize hot paths.
1465+
subtype_ss = subtype.serial_size()
1466+
vec_ss = vsize * subtype_ss if subtype_ss is not None else None
14611467
return type('%s(%s)' % (cls.cass_parameterized_type_with([]), vsize), (cls,),
1462-
{'vector_size': vsize, 'subtype': subtype, '_vector_struct': vector_struct, '_numpy_dtype': numpy_dtype})
1468+
{'vector_size': vsize, 'subtype': subtype, '_vector_struct': vector_struct,
1469+
'_numpy_dtype': numpy_dtype, '_subtype_serial_size': subtype_ss, '_serial_size': vec_ss})
14631470

14641471
@classmethod
14651472
def deserialize(cls, byts, protocol_version):
1466-
serialized_size = cls.subtype.serial_size()
1473+
serialized_size = cls._subtype_serial_size
14671474
if serialized_size is not None:
14681475
expected_byte_size = serialized_size * cls.vector_size
14691476
if len(byts) != expected_byte_size:
@@ -1532,7 +1539,7 @@ def serialize(cls, v, protocol_version):
15321539
"Expected sequence of size {0} for vector of type {1} and dimension {0}, observed sequence of length {2}"\
15331540
.format(cls.vector_size, cls.subtype.typename, v_length))
15341541

1535-
serialized_size = cls.subtype.serial_size()
1542+
serialized_size = cls._subtype_serial_size
15361543
# Bulk serialization for known numeric types (symmetric with struct.unpack in deserialize)
15371544
if cls._vector_struct is not None and serialized_size is not None:
15381545
return cls._vector_struct.pack(*v)

0 commit comments

Comments
 (0)