feat: speed up marshalling arrays (#87)
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
import cython
|
import cython
|
||||||
|
|
||||||
|
|
||||||
|
cdef bytes PACKED_UINT32_ZERO
|
||||||
|
|
||||||
cdef class Marshaller:
|
cdef class Marshaller:
|
||||||
|
|
||||||
cdef object signature_tree
|
cdef object signature_tree
|
||||||
@@ -32,6 +34,7 @@ cdef class Marshaller:
|
|||||||
@cython.locals(
|
@cython.locals(
|
||||||
array_len=cython.uint,
|
array_len=cython.uint,
|
||||||
written=cython.uint,
|
written=cython.uint,
|
||||||
|
token=cython.str,
|
||||||
array_len_packed=cython.bytes,
|
array_len_packed=cython.bytes,
|
||||||
i=cython.uint,
|
i=cython.uint,
|
||||||
)
|
)
|
||||||
@@ -45,11 +48,13 @@ cdef class Marshaller:
|
|||||||
|
|
||||||
@cython.locals(
|
@cython.locals(
|
||||||
written=cython.uint,
|
written=cython.uint,
|
||||||
|
size=cython.uint,
|
||||||
)
|
)
|
||||||
cdef _write_single(self, object type_, object body)
|
cdef _write_single(self, object type_, object body)
|
||||||
|
|
||||||
@cython.locals(
|
@cython.locals(
|
||||||
written=cython.uint,
|
written=cython.uint,
|
||||||
|
t=cython.str,
|
||||||
)
|
)
|
||||||
cpdef write_dict_entry(self, object type_, object body)
|
cpdef write_dict_entry(self, object type_, object body)
|
||||||
|
|
||||||
@@ -57,6 +62,7 @@ cdef class Marshaller:
|
|||||||
|
|
||||||
@cython.locals(
|
@cython.locals(
|
||||||
offset=cython.ulong,
|
offset=cython.ulong,
|
||||||
size=cython.int
|
size=cython.uint,
|
||||||
|
t=cython.str,
|
||||||
)
|
)
|
||||||
cdef _construct_buffer(self)
|
cdef _construct_buffer(self)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
|
|||||||
from ..signature import SignatureType, Variant, get_signature_tree
|
from ..signature import SignatureType, Variant, get_signature_tree
|
||||||
|
|
||||||
PACK_UINT32 = Struct("<I").pack
|
PACK_UINT32 = Struct("<I").pack
|
||||||
|
PACKED_UINT32_ZERO = PACK_UINT32(0)
|
||||||
|
|
||||||
|
|
||||||
class Marshaller:
|
class Marshaller:
|
||||||
@@ -42,19 +43,21 @@ class Marshaller:
|
|||||||
def _write_signature(self, signature) -> int:
|
def _write_signature(self, signature) -> int:
|
||||||
signature_bytes = signature.encode()
|
signature_bytes = signature.encode()
|
||||||
signature_len = len(signature)
|
signature_len = len(signature)
|
||||||
self._buf.append(signature_len)
|
buf = self._buf
|
||||||
self._buf.extend(signature_bytes)
|
buf.append(signature_len)
|
||||||
self._buf.append(0)
|
buf.extend(signature_bytes)
|
||||||
|
buf.append(0)
|
||||||
return signature_len + 2
|
return signature_len + 2
|
||||||
|
|
||||||
def write_string(self, value, _=None) -> int:
|
def write_string(self, value, _=None) -> int:
|
||||||
value_bytes = value.encode()
|
value_bytes = value.encode()
|
||||||
value_len = len(value)
|
value_len = len(value)
|
||||||
written = self._align(4) + 4
|
written = self._align(4) + 4
|
||||||
self._buf.extend(PACK_UINT32(value_len))
|
buf = self._buf
|
||||||
self._buf.extend(value_bytes)
|
buf.extend(PACK_UINT32(value_len))
|
||||||
|
buf.extend(value_bytes)
|
||||||
written += value_len
|
written += value_len
|
||||||
self._buf.append(0)
|
buf.append(0)
|
||||||
written += 1
|
written += 1
|
||||||
return written
|
return written
|
||||||
|
|
||||||
@@ -67,28 +70,30 @@ class Marshaller:
|
|||||||
# TODO max array size is 64MiB (67108864 bytes)
|
# TODO max array size is 64MiB (67108864 bytes)
|
||||||
written = self._align(4)
|
written = self._align(4)
|
||||||
# length placeholder
|
# length placeholder
|
||||||
offset = len(self._buf)
|
buf = self._buf
|
||||||
|
offset = len(buf)
|
||||||
written += self._align(4) + 4
|
written += self._align(4) + 4
|
||||||
self._buf.extend(PACK_UINT32(0))
|
buf.extend(PACKED_UINT32_ZERO)
|
||||||
child_type = type_.children[0]
|
child_type = type_.children[0]
|
||||||
|
token = child_type.token
|
||||||
|
|
||||||
if child_type.token in "xtd{(":
|
if token in "xtd{(":
|
||||||
# the first alignment is not included in array size
|
# the first alignment is not included in array size
|
||||||
written += self._align(8)
|
written += self._align(8)
|
||||||
|
|
||||||
array_len = 0
|
array_len = 0
|
||||||
if child_type.token == "{":
|
if token == "{":
|
||||||
for key, value in array.items():
|
for key, value in array.items():
|
||||||
array_len += self.write_dict_entry([key, value], child_type)
|
array_len += self.write_dict_entry([key, value], child_type)
|
||||||
elif child_type.token == "y":
|
elif token == "y":
|
||||||
array_len = len(array)
|
array_len = len(array)
|
||||||
self._buf.extend(array)
|
buf.extend(array)
|
||||||
elif child_type.token in self._writers:
|
elif token in self._writers:
|
||||||
writer, packer, size = self._writers[child_type.token]
|
writer, packer, size = self._writers[token]
|
||||||
if not writer:
|
if not writer:
|
||||||
for value in array:
|
for value in array:
|
||||||
array_len += self._align(size) + size
|
array_len += self._align(size) + size
|
||||||
self._buf.extend(packer(value))
|
buf.extend(packer(value))
|
||||||
else:
|
else:
|
||||||
for value in array:
|
for value in array:
|
||||||
array_len += writer(self, value, child_type)
|
array_len += writer(self, value, child_type)
|
||||||
@@ -99,7 +104,7 @@ class Marshaller:
|
|||||||
|
|
||||||
array_len_packed = PACK_UINT32(array_len)
|
array_len_packed = PACK_UINT32(array_len)
|
||||||
for i in range(offset, offset + 4):
|
for i in range(offset, offset + 4):
|
||||||
self._buf[i] = array_len_packed[i - offset]
|
buf[i] = array_len_packed[i - offset]
|
||||||
|
|
||||||
return written + array_len
|
return written + array_len
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user