Skip to content

Commit 3a9031e

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 3a9031e

2 files changed

Lines changed: 46 additions & 10 deletions

File tree

cassandra/obj_parser.pyx

Lines changed: 40 additions & 8 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
@@ -66,16 +74,15 @@ cdef class TupleRowParser(RowParser):
6674
cdef Deserializer deserializer
6775
cdef tuple res = tuple_new(desc.rowsize)
6876

69-
ce_policy = desc.column_encryption_policy
7077
for i in range(rowsize):
7178
# Read the next few bytes
7279
get_buf(reader, &buf)
7380

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

94126
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)