feat: speed up unmarshalling headers (#347)
This commit is contained in:
parent
50b377e4da
commit
5825758991
@ -22,7 +22,18 @@ cdef unsigned int HEADER_SIGNATURE_SIZE
|
||||
cdef unsigned int LITTLE_ENDIAN
|
||||
cdef unsigned int BIG_ENDIAN
|
||||
cdef unsigned int PROTOCOL_VERSION
|
||||
|
||||
|
||||
cdef unsigned int HEADER_PATH_IDX
|
||||
cdef unsigned int HEADER_INTERFACE_IDX
|
||||
cdef unsigned int HEADER_MEMBER_IDX
|
||||
cdef unsigned int HEADER_ERROR_NAME_IDX
|
||||
cdef unsigned int HEADER_REPLY_SERIAL_IDX
|
||||
cdef unsigned int HEADER_DESTINATION_IDX
|
||||
cdef unsigned int HEADER_SENDER_IDX
|
||||
cdef unsigned int HEADER_SIGNATURE_IDX
|
||||
cdef unsigned int HEADER_UNIX_FDS_IDX
|
||||
|
||||
cdef cython.list HEADER_IDX_TO_ARG_NAME
|
||||
|
||||
cdef str UINT32_CAST
|
||||
@ -95,6 +106,8 @@ cdef unsigned int TOKEN_LEFT_PAREN_AS_INT
|
||||
cdef object MARSHALL_STREAM_END_ERROR
|
||||
cdef object DEFAULT_BUFFER_SIZE
|
||||
|
||||
cdef list _EMPTY_HEADERS
|
||||
|
||||
cdef cython.uint EAGAIN
|
||||
cdef cython.uint EWOULDBLOCK
|
||||
|
||||
@ -222,9 +235,10 @@ cdef class Unmarshaller:
|
||||
|
||||
@cython.locals(
|
||||
body=cython.list,
|
||||
header_fields=cython.dict,
|
||||
header_fields=cython.list,
|
||||
token_as_int=cython.uint,
|
||||
signature=cython.str,
|
||||
message=Message
|
||||
)
|
||||
cdef _read_body(self)
|
||||
|
||||
@ -237,5 +251,6 @@ cdef class Unmarshaller:
|
||||
o=cython.ulong,
|
||||
token_as_int=cython.uint,
|
||||
signature_len=cython.uint,
|
||||
headers=cython.list
|
||||
)
|
||||
cdef cython.dict _header_fields(self, unsigned int header_length)
|
||||
cdef cython.list _header_fields(self, unsigned int header_length)
|
||||
|
||||
@ -134,8 +134,18 @@ HEADER_IDX_TO_ARG_NAME = [
|
||||
"signature",
|
||||
"unix_fds",
|
||||
]
|
||||
HEADER_PATH_IDX = HEADER_IDX_TO_ARG_NAME.index("path")
|
||||
HEADER_INTERFACE_IDX = HEADER_IDX_TO_ARG_NAME.index("interface")
|
||||
HEADER_MEMBER_IDX = HEADER_IDX_TO_ARG_NAME.index("member")
|
||||
HEADER_ERROR_NAME_IDX = HEADER_IDX_TO_ARG_NAME.index("error_name")
|
||||
HEADER_REPLY_SERIAL_IDX = HEADER_IDX_TO_ARG_NAME.index("reply_serial")
|
||||
HEADER_DESTINATION_IDX = HEADER_IDX_TO_ARG_NAME.index("destination")
|
||||
HEADER_SENDER_IDX = HEADER_IDX_TO_ARG_NAME.index("sender")
|
||||
HEADER_SIGNATURE_IDX = HEADER_IDX_TO_ARG_NAME.index("signature")
|
||||
HEADER_UNIX_FDS_IDX = HEADER_IDX_TO_ARG_NAME.index("unix_fds")
|
||||
|
||||
_EMPTY_HEADERS = [None] * len(HEADER_IDX_TO_ARG_NAME)
|
||||
|
||||
_SignatureType = SignatureType
|
||||
_int = int
|
||||
|
||||
@ -596,12 +606,12 @@ class Unmarshaller:
|
||||
result_list.append(reader(self, child_type))
|
||||
return result_list
|
||||
|
||||
def _header_fields(self, header_length: _int) -> dict[str, Any]:
|
||||
def _header_fields(self, header_length: _int) -> list[Any]:
|
||||
"""Header fields are always a(yv)."""
|
||||
beginning_pos = self._pos
|
||||
headers = {}
|
||||
buf = self._buf
|
||||
readers = self._readers
|
||||
headers = _EMPTY_HEADERS.copy()
|
||||
while self._pos - beginning_pos < header_length:
|
||||
# Now read the y (byte) of struct (yv)
|
||||
self._pos += (-self._pos & 7) + 1 # align 8 + 1 for 'y' byte
|
||||
@ -616,18 +626,19 @@ class Unmarshaller:
|
||||
continue
|
||||
token_as_int = buf[o]
|
||||
# Now that we have the token we can read the variant value
|
||||
key = HEADER_IDX_TO_ARG_NAME[field_0]
|
||||
# Strings and signatures are the most common types
|
||||
# so we inline them for performance
|
||||
if token_as_int == TOKEN_O_AS_INT or token_as_int == TOKEN_S_AS_INT:
|
||||
headers[key] = self._read_string_unpack()
|
||||
headers[field_0] = self._read_string_unpack()
|
||||
elif token_as_int == TOKEN_G_AS_INT:
|
||||
headers[key] = self._read_signature()
|
||||
headers[field_0] = self._read_signature()
|
||||
else:
|
||||
token = buf[o : o + signature_len].decode()
|
||||
# There shouldn't be any other types in the header
|
||||
# but just in case, we'll read it using the slow path
|
||||
headers[key] = readers[token](self, get_signature_tree(token).types[0])
|
||||
headers[field_0] = readers[token](
|
||||
self, get_signature_tree(token).types[0]
|
||||
)
|
||||
return headers
|
||||
|
||||
def _read_header(self) -> None:
|
||||
@ -694,7 +705,7 @@ class Unmarshaller:
|
||||
self._pos = HEADER_ARRAY_OF_STRUCT_SIGNATURE_POSITION
|
||||
header_fields = self._header_fields(self._header_len)
|
||||
self._pos += -self._pos & 7 # align 8
|
||||
signature = header_fields.pop("signature", "")
|
||||
signature = header_fields[HEADER_SIGNATURE_IDX]
|
||||
if not self._body_len:
|
||||
tree = SIGNATURE_TREE_EMPTY
|
||||
body: list[Any] = []
|
||||
@ -749,7 +760,13 @@ class Unmarshaller:
|
||||
# The D-Bus implementation already validates the message,
|
||||
# so we don't need to do it again.
|
||||
validate=False,
|
||||
**header_fields,
|
||||
destination=header_fields[HEADER_DESTINATION_IDX],
|
||||
path=header_fields[HEADER_PATH_IDX],
|
||||
interface=header_fields[HEADER_INTERFACE_IDX],
|
||||
member=header_fields[HEADER_MEMBER_IDX],
|
||||
reply_serial=header_fields[HEADER_REPLY_SERIAL_IDX],
|
||||
error_name=header_fields[HEADER_ERROR_NAME_IDX],
|
||||
sender=header_fields[HEADER_SENDER_IDX],
|
||||
)
|
||||
self._read_complete = True
|
||||
|
||||
|
||||
@ -107,12 +107,12 @@ class Message:
|
||||
message_type: MessageType = MESSAGE_TYPE_METHOD_CALL,
|
||||
flags: Union[MessageFlag, int] = MESSAGE_FLAG_NONE,
|
||||
error_name: Optional[Union[str, ErrorType]] = None,
|
||||
reply_serial: int = 0,
|
||||
reply_serial: Optional[int] = None,
|
||||
sender: Optional[str] = None,
|
||||
unix_fds: list[int] = [],
|
||||
signature: Optional[Union[SignatureTree, str]] = None,
|
||||
body: list[Any] = [],
|
||||
serial: int = 0,
|
||||
serial: Optional[int] = None,
|
||||
validate: bool = True,
|
||||
) -> None:
|
||||
self.destination = destination
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user