From 18ab9f80b0bc97bfa328bf04ccb1485905493066 Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Fri, 8 Apr 2022 15:20:33 +0100 Subject: [PATCH] target: Expose Target(max_async=50) parameter Allow the user to set a maximum number of conrruent connections used to dispatch non-blocking commands when using the async API. --- devlib/target.py | 38 +++++++++++++++++++++++++++++++------- doc/target.rst | 13 ++++++++----- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/devlib/target.py b/devlib/target.py index cd49900..78930b3 100644 --- a/devlib/target.py +++ b/devlib/target.py @@ -306,9 +306,11 @@ class Target(object): load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=None, - is_container=False + is_container=False, + max_async=50, ): self._async_pool = None + self._async_pool_size = None self._unused_conns = set() self._is_rooted = None @@ -352,7 +354,7 @@ class Target(object): self.modules = merge_lists(*module_lists, duplicates='first') self._update_modules('early') if connect: - self.connect() + self.connect(max_async=max_async) def __getstate__(self): # tls_property will recreate the underlying value automatically upon @@ -363,12 +365,25 @@ class Target(object): for k, v in inspect.getmembers(self.__class__) if isinstance(v, _BoundTLSProperty) } + ignored.update(( + '_async_pool', + '_unused_conns', + )) return { k: v for k, v in self.__dict__.items() if k not in ignored } + def __setstate__(self, dct): + self.__dict__ = dct + pool_size = self._async_pool_size + if pool_size is None: + self._async_pool = None + else: + self._async_pool = ThreadPoolExecutor(pool_size) + self._unused_conns = set() + # connection and initialization @asyn.asyncf @@ -433,6 +448,7 @@ class Target(object): max_conns = len(conns) self.logger.debug(f'Detected max number of async commands: {max_conns}') + self._async_pool_size = max_conns self._async_pool = ThreadPoolExecutor(max_conns) @asyn.asyncf @@ -1547,6 +1563,7 @@ class LinuxTarget(Target): shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=SshConnection, is_container=False, + max_async=50, ): super(LinuxTarget, self).__init__(connection_settings=connection_settings, platform=platform, @@ -1557,7 +1574,8 @@ class LinuxTarget(Target): load_default_modules=load_default_modules, shell_prompt=shell_prompt, conn_cls=conn_cls, - is_container=is_container) + is_container=is_container, + max_async=max_async) def wait_boot_complete(self, timeout=10): pass @@ -1752,6 +1770,7 @@ class AndroidTarget(Target): conn_cls=AdbConnection, package_data_directory="/data/data", is_container=False, + max_async=50, ): super(AndroidTarget, self).__init__(connection_settings=connection_settings, platform=platform, @@ -1762,7 +1781,8 @@ class AndroidTarget(Target): load_default_modules=load_default_modules, shell_prompt=shell_prompt, conn_cls=conn_cls, - is_container=is_container) + is_container=is_container, + max_async=max_async) self.package_data_directory = package_data_directory self._init_logcat_lock() @@ -2823,6 +2843,7 @@ class LocalLinuxTarget(LinuxTarget): shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=LocalConnection, is_container=False, + max_async=50, ): super(LocalLinuxTarget, self).__init__(connection_settings=connection_settings, platform=platform, @@ -2833,7 +2854,8 @@ class LocalLinuxTarget(LinuxTarget): load_default_modules=load_default_modules, shell_prompt=shell_prompt, conn_cls=conn_cls, - is_container=is_container) + is_container=is_container, + max_async=max_async) def _resolve_paths(self): if self.working_directory is None: @@ -2906,7 +2928,8 @@ class ChromeOsTarget(LinuxTarget): load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, package_data_directory="/data/data", - is_container=False + is_container=False, + max_async=50, ): self.supports_android = None @@ -2932,7 +2955,8 @@ class ChromeOsTarget(LinuxTarget): load_default_modules=load_default_modules, shell_prompt=shell_prompt, conn_cls=SshConnection, - is_container=is_container) + is_container=is_container, + max_async=max_async) # We can't determine if the target supports android until connected to the linux host so # create unconditionally. diff --git a/doc/target.rst b/doc/target.rst index f17cfe4..17b2bbd 100644 --- a/doc/target.rst +++ b/doc/target.rst @@ -3,7 +3,7 @@ Target ====== -.. class:: Target(connection_settings=None, platform=None, working_directory=None, executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=None) +.. class:: Target(connection_settings=None, platform=None, working_directory=None, executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=None, max_async=50) :class:`~devlib.target.Target` is the primary interface to the remote device. All interactions with the device are performed via a @@ -76,6 +76,9 @@ Target :param conn_cls: This is the type of connection that will be used to communicate with the device. + :param max_async: Maximum number of opened connections to the target used to + issue non-blocking commands when using the async API. + .. attribute:: Target.core_names This is a list containing names of CPU cores on the target, in the order in @@ -606,7 +609,7 @@ Target Linux Target ------------ -.. class:: LinuxTarget(connection_settings=None, platform=None, working_directory=None, executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=SshConnection, is_container=False,) +.. class:: LinuxTarget(connection_settings=None, platform=None, working_directory=None, executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=SshConnection, is_container=False, max_async=50) :class:`LinuxTarget` is a subclass of :class:`~devlib.target.Target` with customisations specific to a device running linux. @@ -615,7 +618,7 @@ Linux Target Local Linux Target ------------------ -.. class:: LocalLinuxTarget(connection_settings=None, platform=None, working_directory=None, executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=SshConnection, is_container=False,) +.. class:: LocalLinuxTarget(connection_settings=None, platform=None, working_directory=None, executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=SshConnection, is_container=False, max_async=50) :class:`LocalLinuxTarget` is a subclass of :class:`~devlib.target.LinuxTarget` with customisations specific to using @@ -625,7 +628,7 @@ Local Linux Target Android Target --------------- -.. class:: AndroidTarget(connection_settings=None, platform=None, working_directory=None, executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=AdbConnection, package_data_directory="/data/data") +.. class:: AndroidTarget(connection_settings=None, platform=None, working_directory=None, executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, conn_cls=AdbConnection, package_data_directory="/data/data", max_async=50) :class:`AndroidTarget` is a subclass of :class:`~devlib.target.Target` with additional features specific to a device running Android. @@ -773,7 +776,7 @@ Android Target ChromeOS Target --------------- -.. class:: ChromeOsTarget(connection_settings=None, platform=None, working_directory=None, executables_directory=None, android_working_directory=None, android_executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, package_data_directory="/data/data") +.. class:: ChromeOsTarget(connection_settings=None, platform=None, working_directory=None, executables_directory=None, android_working_directory=None, android_executables_directory=None, connect=True, modules=None, load_default_modules=True, shell_prompt=DEFAULT_SHELL_PROMPT, package_data_directory="/data/data", max_async=50) :class:`ChromeOsTarget` is a subclass of :class:`LinuxTarget` with additional features specific to a device running ChromeOS for example,