Skip to content

Commit ad8b6f9

Browse files
committed
(improvement)Optimize column_encryption_policy checks in Cython's unpack_row() function
Very similar to the native Python code, separate the two cases, if column encryption (CE) policy is not enabled, the code is substantially simplified. If it is, it's slightly more elaborate. Decided to have two loops in two functions, one for each case, for performance reasons, even if readability-wise it's not as great. AI agreed with me: Recommendation: Keep it as is. In high-performance Cython code like this, duplicating a small block of code Fixes: #639 Signed-off-by: Yaniv Kaul <yaniv.kaul@scylladb.com>
1 parent dd09f58 commit ad8b6f9

2 files changed

Lines changed: 46 additions & 9 deletions

File tree

cassandra/obj_parser.pyx

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ cdef class ListParser(ColumnParser):
3131
cdef Py_ssize_t i, rowcount
3232
rowcount = read_int(reader)
3333
cdef RowParser rowparser = TupleRowParser()
34-
return [rowparser.unpack_row(reader, desc) for i in range(rowcount)]
34+
if desc.column_encryption_policy:
35+
return [rowparser.unpack_ce_row(reader, desc) for i in range(rowcount)]
36+
else:
37+
return [rowparser.unpack_row(reader, desc) for i in range(rowcount)]
3538

3639

3740
cdef class LazyParser(ColumnParser):
@@ -47,17 +50,22 @@ def parse_rows_lazy(BytesIOReader reader, ParseDesc desc):
4750
cdef Py_ssize_t i, rowcount
4851
rowcount = read_int(reader)
4952
cdef RowParser rowparser = TupleRowParser()
50-
return (rowparser.unpack_row(reader, desc) for i in range(rowcount))
53+
if desc.column_encryption_policy:
54+
return (rowparser.unpack_ce_row(reader, desc) for i in range(rowcount))
55+
else:
56+
return (rowparser.unpack_row(reader, desc) for i in range(rowcount))
5157

5258

5359
cdef class TupleRowParser(RowParser):
5460
"""
5561
Parse a single returned row into a tuple of objects:
5662
5763
(obj1, ..., objN)
64+
If CE (Column encryption) policy is enabled - use unpack_ce_row(),
65+
otherwsise use unpack_row()
5866
"""
5967

60-
cpdef unpack_row(self, BytesIOReader reader, ParseDesc desc):
68+
cpdef unpack_ce_row(self, BytesIOReader reader, ParseDesc desc):
6169
assert desc.rowsize >= 0
6270

6371
cdef Buffer buf
@@ -73,9 +81,9 @@ cdef class TupleRowParser(RowParser):
7381

7482
# Deserialize bytes to python object
7583
deserializer = desc.deserializers[i]
76-
coldesc = desc.coldescs[i]
77-
uses_ce = ce_policy and ce_policy.contains_column(coldesc)
7884
try:
85+
coldesc = desc.coldescs[i]
86+
uses_ce = ce_policy.contains_column(coldesc)
7987
if uses_ce:
8088
col_type = ce_policy.column_type(coldesc)
8189
decrypted_bytes = ce_policy.decrypt(coldesc, to_bytes(&buf))
@@ -84,11 +92,36 @@ cdef class TupleRowParser(RowParser):
8492
val = from_binary(deserializer, &newbuf, desc.protocol_version)
8593
else:
8694
val = from_binary(deserializer, &buf, desc.protocol_version)
95+
# Insert new object into tuple
96+
tuple_set(res, i, val)
97+
except Exception as e:
98+
raise DriverException('Failed decoding result column "%s" of type %s: %s' % (desc.colnames[i],
99+
desc.coltypes[i].cql_parameterized_type(),
100+
str(e)))
101+
102+
return res
103+
104+
cpdef unpack_row(self, BytesIOReader reader, ParseDesc desc):
105+
assert desc.rowsize >= 0
106+
107+
cdef Buffer buf
108+
cdef Py_ssize_t i, rowsize = desc.rowsize
109+
cdef Deserializer deserializer
110+
cdef tuple res = tuple_new(desc.rowsize)
111+
112+
for i in range(rowsize):
113+
# Read the next few bytes
114+
get_buf(reader, &buf)
115+
116+
# Deserialize bytes to python object
117+
deserializer = desc.deserializers[i]
118+
try:
119+
val = from_binary(deserializer, &buf, desc.protocol_version)
120+
# Insert new object into tuple
121+
tuple_set(res, i, val)
87122
except Exception as e:
88123
raise DriverException('Failed decoding result column "%s" of type %s: %s' % (desc.colnames[i],
89124
desc.coltypes[i].cql_parameterized_type(),
90125
str(e)))
91-
# Insert new object into tuple
92-
tuple_set(res, i, val)
93126

94127
return res

cassandra/row_parser.pyx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ def make_recv_results_rows(ColumnParser colparser):
4444
reader.buf_ptr = reader.buf
4545
reader.pos = 0
4646
rowcount = read_int(reader)
47-
for i in range(rowcount):
48-
rowparser.unpack_row(reader, desc)
47+
if desc.column_encryption_policy:
48+
for i in range(rowcount):
49+
rowparser.unpack_ce_row(reader, desc)
50+
else:
51+
for i in range(rowcount):
52+
rowparser.unpack_row(reader, desc)
4953

5054
return recv_results_rows

0 commit comments

Comments
 (0)