Browse Source

Testing with a wallet with a ~1000 unpaid/expired payment requests,

with the Qt gui, the python process saturates one of my CPU cores to 100%.
This is because main_window.timer_actions() calls request_list.refresh_all()
every 0.5 seconds, which iterates over all unpaid payreqs, and does a
scriptpubkey->address->scriptpubkey conversion.

Trace of the hot path:
```
  File "/home/user/wspace/electrum/./run_electrum", line 510, in <module>
    main()
  File "/home/user/wspace/electrum/./run_electrum", line 421, in main
    handle_cmd(
  File "/home/user/wspace/electrum/./run_electrum", line 439, in handle_cmd
    d.run_gui(config, plugins)
  File "/home/user/wspace/electrum/electrum/daemon.py", line 581, in run_gui
    self.gui_object.main()
  File "/home/user/wspace/electrum/electrum/gui/qt/__init__.py", line 469, in main
    self.app.exec_()
  File "/home/user/wspace/electrum/electrum/gui/qt/main_window.py", line 861, in timer_actions
    self.receive_tab.request_list.refresh_all()
  File "/home/user/wspace/electrum/electrum/gui/qt/util.py", line 821, in refresh_all
    self.refresh_row(key, row)
  File "/home/user/wspace/electrum/electrum/gui/qt/request_list.py", line 126, in refresh_row
    status = self.wallet.get_invoice_status(request)
  File "/home/user/wspace/electrum/electrum/wallet.py", line 2330, in get_invoice_status
    paid, conf = self.is_onchain_invoice_paid(invoice)
  File "/home/user/wspace/electrum/electrum/wallet.py", line 1118, in is_onchain_invoice_paid
    is_paid, conf_needed, relevant_txs = self._is_onchain_invoice_paid(invoice)
  File "/home/user/wspace/electrum/electrum/wallet.py", line 1085, in _is_onchain_invoice_paid
    outputs = invoice.get_outputs()
  File "/home/user/wspace/electrum/electrum/invoices.py", line 130, in get_outputs
    traceback.print_stack()
```

These commits drastically reduce the CPU utilisation.
master
SomberNight 3 years ago
parent
commit
3ce2986c1f
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 2
      electrum/gui/qt/util.py
  2. 11
      electrum/invoices.py
  3. 11
      electrum/transaction.py

2
electrum/gui/qt/util.py

@ -813,6 +813,8 @@ class MyTreeView(QTreeView):
return row
def refresh_all(self):
if self.maybe_defer_update():
return
for row in range(0, self.std_model.rowCount()):
item = self.std_model.item(row, 0)
key = item.data(self.key_role)

11
electrum/invoices.py

@ -1,5 +1,5 @@
import time
from typing import TYPE_CHECKING, List, Optional, Union, Dict, Any
from typing import TYPE_CHECKING, List, Optional, Union, Dict, Any, Sequence
from decimal import Decimal
import attr
@ -126,16 +126,13 @@ class Invoice(StoredObject):
address = self._lnaddr.get_fallback_address() or None
return address
def get_outputs(self):
if self.is_lightning():
def get_outputs(self) -> Sequence[PartialTxOutput]:
outputs = self.outputs or []
if not outputs:
address = self.get_address()
amount = self.get_amount_sat()
if address and amount is not None:
outputs = [PartialTxOutput.from_address_and_value(address, int(amount))]
else:
outputs = []
else:
outputs = self.outputs
return outputs
def can_be_paid_onchain(self) -> bool:

11
electrum/transaction.py

@ -148,9 +148,18 @@ class TxOutput:
return cls(scriptpubkey=bfh(addr), value=val)
raise Exception(f"unexpected legacy address type: {_type}")
@property
def scriptpubkey(self) -> bytes:
return self._scriptpubkey
@scriptpubkey.setter
def scriptpubkey(self, scriptpubkey: bytes):
self._scriptpubkey = scriptpubkey
self._address = get_address_from_output_script(scriptpubkey)
@property
def address(self) -> Optional[str]:
return get_address_from_output_script(self.scriptpubkey) # TODO cache this?
return self._address
def get_ui_address_str(self) -> str:
addr = self.address

Loading…
Cancel
Save