|
26 | 26 | from aiorpcx import (Event, JSONRPCAutoDetect, JSONRPCConnection,
|
27 | 27 | ReplyAndDisconnect, Request, RPCError, RPCSession,
|
28 | 28 | handler_invocation, serve_rs, serve_ws, sleep,
|
29 |
| - NewlineFramer, TaskTimeout, timeout_after) |
| 29 | + NewlineFramer, TaskTimeout, timeout_after, run_in_thread) |
30 | 30 |
|
31 | 31 | import electrumx
|
32 | 32 | import electrumx.lib.util as util
|
@@ -167,7 +167,8 @@ def __init__(
|
167 | 167 |
|
168 | 168 | # Set up the RPC request handlers
|
169 | 169 | cmds = ('add_peer daemon_url disconnect getinfo groups log peers '
|
170 |
| - 'query reorg sessions stop'.split()) |
| 170 | + 'query reorg sessions stop debug_memusage_list_all_objects ' |
| 171 | + 'debug_memusage_get_random_backref_chain'.split()) |
171 | 172 | LocalRPC.request_handlers = {cmd: getattr(self, 'rpc_' + cmd)
|
172 | 173 | for cmd in cmds}
|
173 | 174 |
|
@@ -593,6 +594,38 @@ async def rpc_reorg(self, count):
|
593 | 594 | raise RPCError(BAD_REQUEST, 'still catching up with daemon')
|
594 | 595 | return f'scheduled a reorg of {count:,d} blocks'
|
595 | 596 |
|
| 597 | + async def rpc_debug_memusage_list_all_objects(self, limit: int) -> str: |
| 598 | + """Return a string listing the most common types in memory.""" |
| 599 | + import objgraph # optional dependency |
| 600 | + import io |
| 601 | + with io.StringIO() as fd: |
| 602 | + objgraph.show_most_common_types( |
| 603 | + limit=limit, |
| 604 | + shortnames=False, |
| 605 | + file=fd) |
| 606 | + return fd.getvalue() |
| 607 | + |
| 608 | + async def rpc_debug_memusage_get_random_backref_chain(self, objtype: str) -> str: |
| 609 | + """Return a dotfile as text containing the backref chain |
| 610 | + for a randomly selected object of type objtype. |
| 611 | +
|
| 612 | + Warning: very slow! and it blocks the server. |
| 613 | +
|
| 614 | + To convert to image: |
| 615 | + $ dot -Tps filename.dot -o outfile.ps |
| 616 | + """ |
| 617 | + import objgraph # optional dependency |
| 618 | + import random |
| 619 | + import io |
| 620 | + with io.StringIO() as fd: |
| 621 | + await run_in_thread(lambda: |
| 622 | + objgraph.show_chain( |
| 623 | + objgraph.find_backref_chain( |
| 624 | + random.choice(objgraph.by_type(objtype)), |
| 625 | + objgraph.is_proper_module), |
| 626 | + output=fd)) |
| 627 | + return fd.getvalue() |
| 628 | + |
596 | 629 | # --- External Interface
|
597 | 630 |
|
598 | 631 | async def serve(self, notifications, event):
|
|
0 commit comments