From f36cc5b6e02bf34105e6129296decc29e105cf4f Mon Sep 17 00:00:00 2001 From: SomberNight Date: Sat, 29 Aug 2020 04:22:55 +0200 Subject: [PATCH] trezor: cache whether TrezorBridge is available to speedup scan_devices If the Bridge is unavailable, on my machine it takes 2 seconds to timeout. i.e. call_bridge("enumerate") and BridgeTransport.enumerate() both take 2 seconds each. With this change, if the Bridge is unavailable, DeviceMgr.scan_devices() takes 4 seconds less. In below log, with 6 different hw devices connected, scan time was originally ~7.5 seconds; with this change it became ~3.5 seconds. Now the time is dominated by WebUsbTransport.enumerate(), called by Trezor, KeepKey, SafeT, ~1.1 seconds each. ----- I | plugin.DeviceMgr | scan_devices() entered. 1598666278.6756 I | plugin.DeviceMgr | scan_devices(). _scan_devices_with_hid() DONE. 1598666278.7583 I | plugin.DeviceMgr | scan_devices(). starting custom enumeration loop. 1598666278.7593 I | plugin.DeviceMgr | scan_devices(). custom enumeration iter DONE, for >. 1598666279.9345 I | plugins.trezor.qt.Plugin | trezor custom enumeration entered. 1598666279.9345 I | plugins.trezor.qt.Plugin | trezor custom enumeration. call_bridge('enumerate') DONE. 1598666281.9385 >> trezorlib enumerating DONE at 1598666283.9500. >> trezorlib enumerating DONE at 1598666285.0427. >> trezorlib enumerating DONE at 1598666285.1198. >> trezorlib enumerating DONE at 1598666285.1237. I | plugins.trezor.qt.Plugin | trezor custom enumeration. trezorlib.transport.enumerate_devices() DONE. 1598666285.1257 I | plugin.DeviceMgr | scan_devices(). custom enumeration iter DONE, for >. 1598666285.1257 I | plugin.DeviceMgr | scan_devices(). custom enumeration iter DONE, for >. 1598666286.2251 I | plugin.DeviceMgr | scan_devices(). custom enumeration iter DONE, for >. 1598666286.2251 I | plugin.DeviceMgr | scan_devices(). custom enumeration loop DONE. 1598666286.2251 I | plugin.DeviceMgr | scan_devices(). find out what was disconnected DONE. 1598666286.2251 I | plugin.DeviceMgr | scan_devices(). Unpair disconnected devices DONE. 1598666286.2251 --- electrum/plugins/trezor/trezor.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/electrum/plugins/trezor/trezor.py b/electrum/plugins/trezor/trezor.py index 6c4f2d3f0..4ad479f6d 100644 --- a/electrum/plugins/trezor/trezor.py +++ b/electrum/plugins/trezor/trezor.py @@ -130,6 +130,7 @@ class TrezorPlugin(HW_PluginBase): if not self.libraries_available: return self.device_manager().register_enumerate_func(self.enumerate) + self._is_bridge_available = None def get_library_version(self): import trezorlib @@ -142,17 +143,29 @@ class TrezorPlugin(HW_PluginBase): else: raise LibraryFoundButUnusable(library_version=version) + def is_bridge_available(self) -> bool: + # Testing whether the Bridge is available can take several seconds + # (when it is not), as it is slow to timeout, hence we cache it. + if self._is_bridge_available is None: + try: + call_bridge("enumerate") + except Exception: + self._is_bridge_available = False + # never again try with Bridge due to slow timeout + BridgeTransport.ENABLED = False + else: + self._is_bridge_available = True + return self._is_bridge_available + def enumerate(self): # If there is a bridge, prefer that. # On Windows, the bridge runs as Admin (and Electrum usually does not), # so the bridge has better chances of finding devices. see #5420 # This also avoids duplicate entries. - try: - call_bridge("enumerate") - except Exception: - devices = trezorlib.transport.enumerate_devices() - else: + if self.is_bridge_available(): devices = BridgeTransport.enumerate() + else: + devices = trezorlib.transport.enumerate_devices() return [Device(path=d.get_path(), interface_number=-1, id_=d.get_path(),