feat: reduce latency to process messages (#161)

Improve `message_bus.py` `_process_message` performance with a `pxd` file
This commit is contained in:
J. Nick Koston 2022-11-11 08:16:19 -06:00 committed by GitHub
parent 9240bfda6e
commit 113f0c9a32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 14 deletions

View File

@ -24,6 +24,7 @@ def build(setup_kwargs):
[
"src/dbus_fast/aio/message_reader.py",
"src/dbus_fast/message.py",
"src/dbus_fast/message_bus.py",
"src/dbus_fast/signature.py",
"src/dbus_fast/unpack.py",
"src/dbus_fast/_private/marshaller.py",

View File

@ -0,0 +1,29 @@
import cython
from .message cimport Message
cdef object MessageType
cdef object DBusError
cdef object MessageFlag
cdef object MESSAGE_TYPE_CALL
cdef object MESSAGE_TYPE_SIGNAL
cdef class BaseMessageBus:
cdef public object unique_name
cdef public object _disconnected
cdef public object _user_disconnect
cdef public object _method_return_handlers
cdef public object _serial
cdef public cython.list _user_message_handlers
cdef public object _name_owners
cdef public object _bus_address
cdef public object _name_owner_match_rule
cdef public object _match_rules
cdef public object _high_level_client_initialized
cdef public object _ProxyObject
cdef public object _machine_id
cpdef _process_message(self, Message msg)

View File

@ -25,6 +25,9 @@ from .service import ServiceInterface, _Method
from .signature import Variant
from .validators import assert_bus_name_valid, assert_object_path_valid
MESSAGE_TYPE_CALL = MessageType.METHOD_CALL
MESSAGE_TYPE_SIGNAL = MessageType.SIGNAL
class BaseMessageBus:
"""An abstract class to manage a connection to a DBus message bus.
@ -56,6 +59,22 @@ class BaseMessageBus:
:vartype connected: bool
"""
__slots__ = (
"unique_name",
"_disconnected",
"_user_disconnect",
"_method_return_handlers",
"_serial",
"_user_message_handlers",
"_name_owners",
"_bus_address",
"_name_owner_match_rule",
"_match_rules",
"_high_level_client_initialized",
"_ProxyObject",
"_machine_id",
)
def __init__(
self,
bus_address: Optional[str] = None,
@ -620,7 +639,7 @@ class BaseMessageBus:
if "path" in options:
filename = options["path"]
elif "abstract" in options:
filename = f'\0{options["abstract"]}'
filename = b"\0" + options["abstract"].encode()
else:
raise InvalidAddressError(
"got unix transport with unknown path specifier"
@ -770,9 +789,8 @@ class BaseMessageBus:
return SendReply()
def _process_message(self, msg: Message) -> None:
def _process_message(self, msg) -> None:
handled = False
for user_handler in self._user_message_handlers:
try:
result = user_handler(msg)
@ -782,7 +800,7 @@ class BaseMessageBus:
handled = True
break
except DBusError as e:
if msg.message_type == MessageType.METHOD_CALL:
if msg.message_type is MESSAGE_TYPE_CALL:
self.send(e._as_message(msg))
handled = True
break
@ -794,7 +812,7 @@ class BaseMessageBus:
logging.error(
f"A message handler raised an exception: {e}.\n{traceback.format_exc()}"
)
if msg.message_type == MessageType.METHOD_CALL:
if msg.message_type is MESSAGE_TYPE_CALL:
self.send(
Message.new_error(
msg,
@ -805,7 +823,7 @@ class BaseMessageBus:
handled = True
break
if msg.message_type == MessageType.SIGNAL:
if msg.message_type is MESSAGE_TYPE_SIGNAL:
if (
msg.member == "NameOwnerChanged"
and msg.sender == "org.freedesktop.DBus"
@ -817,8 +835,9 @@ class BaseMessageBus:
self._name_owners[name] = new_owner
elif name in self._name_owners:
del self._name_owners[name]
return
elif msg.message_type == MessageType.METHOD_CALL:
if msg.message_type is MESSAGE_TYPE_CALL:
if not handled:
handler = self._find_message_handler(msg)
@ -835,14 +854,14 @@ class BaseMessageBus:
f'{msg.interface}.{msg.member} with signature "{msg.signature}" could not be found',
)
)
return
else:
# An ERROR or a METHOD_RETURN
if msg.reply_serial in self._method_return_handlers:
if not handled:
return_handler = self._method_return_handlers[msg.reply_serial]
return_handler(msg, None)
del self._method_return_handlers[msg.reply_serial]
# An ERROR or a METHOD_RETURN
if msg.reply_serial in self._method_return_handlers:
if not handled:
return_handler = self._method_return_handlers[msg.reply_serial]
return_handler(msg, None)
del self._method_return_handlers[msg.reply_serial]
def _make_method_handler(
self, interface: ServiceInterface, method: _Method