Added thread debug option
CoreConfig now have a boolean thread debug option, when this is enabled, it prints out the CPU usage of each thread to help identify which threads are the most CPU hungry for later optimisation
This commit is contained in:
4 files changed
+143
-13
No files matched your search
@@ -12,6 +12,8 @@ from threading import Lock, Thread
|
||||
import time
|
||||
from typing import Literal
|
||||
from uuid import UUID
|
||||
import os
|
||||
import psutil
|
||||
|
||||
|
||||
from dynalab_core.buffer import ValueBuffer
|
||||
@@ -69,6 +71,67 @@ class Core:
|
||||
|
||||
self._state = "initd"
|
||||
|
||||
self._debug_thread: Thread | None = None
|
||||
|
||||
if self._core_config.thread_debug:
|
||||
self._debug_thread = Thread(
|
||||
target=self._debug_worker, name="dynalab_core_debug_thread", daemon=True
|
||||
)
|
||||
self._debug_thread.start()
|
||||
|
||||
def _debug_worker(self) -> None:
|
||||
|
||||
process = psutil.Process(os.getpid())
|
||||
|
||||
previous = {}
|
||||
|
||||
while not self._stop_event.is_set():
|
||||
current = {
|
||||
thread.id: thread.user_time + thread.system_time
|
||||
for thread in process.threads()
|
||||
}
|
||||
|
||||
names = {
|
||||
thread.native_id: thread.name
|
||||
for thread in threading.enumerate()
|
||||
if thread.native_id is not None
|
||||
}
|
||||
|
||||
usage = []
|
||||
|
||||
for tid, cpu_time in current.items():
|
||||
previous_cpu_time = previous.get(tid, cpu_time)
|
||||
delta = cpu_time - previous_cpu_time
|
||||
|
||||
usage.append(
|
||||
(
|
||||
delta,
|
||||
tid,
|
||||
names.get(tid, "<unknown>"),
|
||||
)
|
||||
)
|
||||
|
||||
for delta, tid, thread_name in sorted(usage, reverse=True):
|
||||
cpu_percent = delta * 100
|
||||
|
||||
log.debug(
|
||||
(
|
||||
f"Thread CPU usage sampled: "
|
||||
f"name={thread_name}, "
|
||||
f"id={tid}, "
|
||||
f"cpu={cpu_percent:.2f}%"
|
||||
),
|
||||
extra={
|
||||
"event": "core.thread_cpu_usage",
|
||||
"thread_name": thread_name,
|
||||
"thread_id": tid,
|
||||
"cpu_percent": cpu_percent,
|
||||
},
|
||||
)
|
||||
|
||||
previous = current
|
||||
time.sleep(1)
|
||||
|
||||
def start(self) -> None:
|
||||
if self._state != "initd":
|
||||
log.warning(
|
||||
|
||||
@@ -8,6 +8,7 @@ from pydantic import BaseModel, Field
|
||||
class CoreConfig(BaseModel):
|
||||
host: str = "127.0.0.1"
|
||||
port: int = Field(default=58763, ge=0, le=65535)
|
||||
thread_debug: bool = False
|
||||
|
||||
def bind_str(self) -> str:
|
||||
return f"{self.host}:{self.port}"
|
||||
+13
-12
@@ -28,7 +28,7 @@ HOST = "127.0.0.1"
|
||||
PORT = 8765
|
||||
DISPLAY_FREQUENCY_HZ = 5.0
|
||||
LOG_HISTORY_SIZE = 1_000
|
||||
VISIBLE_LOG_LINES = 12
|
||||
VISIBLE_LOG_LINES = 20
|
||||
|
||||
signal_id_1: UUID = UUID("3f32cea3-d872-4c16-a0a2-54b57171aeb2")
|
||||
signal_id_2: UUID = UUID("6578ac37-99d1-410c-b3f7-d049339919b2")
|
||||
@@ -55,9 +55,7 @@ class TuiLogHandler(logging.Handler):
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._entries: deque[tuple[str, str, str, str]] = deque(
|
||||
maxlen=LOG_HISTORY_SIZE
|
||||
)
|
||||
self._entries: deque[tuple[str, str, str, str]] = deque(maxlen=LOG_HISTORY_SIZE)
|
||||
self._lock = Lock()
|
||||
self.setFormatter(
|
||||
logging.Formatter(
|
||||
@@ -275,10 +273,10 @@ def main() -> None:
|
||||
dynalab_logger.setLevel(logging.DEBUG)
|
||||
dynalab_logger.propagate = False
|
||||
dynalab_logger.addHandler(log_handler)
|
||||
config = CoreConfig(host=HOST, port=PORT)
|
||||
config = CoreConfig(host=HOST, port=PORT, thread_debug=False)
|
||||
core = Core(config)
|
||||
processing_source = Path(__file__).with_name("process.py").read_text(
|
||||
encoding="utf-8"
|
||||
processing_source = (
|
||||
Path(__file__).with_name("process.py").read_text(encoding="utf-8")
|
||||
)
|
||||
dashboard = Dashboard(core, config, log_handler)
|
||||
|
||||
@@ -312,11 +310,14 @@ def main() -> None:
|
||||
|
||||
try:
|
||||
core.start()
|
||||
with keyboard_input(), Live(
|
||||
dashboard.render(),
|
||||
auto_refresh=False,
|
||||
screen=False,
|
||||
) as live:
|
||||
with (
|
||||
keyboard_input(),
|
||||
Live(
|
||||
dashboard.render(),
|
||||
auto_refresh=False,
|
||||
screen=False,
|
||||
) as live,
|
||||
):
|
||||
while dashboard.running:
|
||||
update_started = time.monotonic()
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ name = "dynalab-core"
|
||||
version = "0.1.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "psutil" },
|
||||
{ name = "psutils" },
|
||||
{ name = "pydantic" },
|
||||
]
|
||||
|
||||
@@ -35,7 +37,11 @@ dev = [
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "pydantic", specifier = ">=2.13.4" }]
|
||||
requires-dist = [
|
||||
{ name = "psutil", specifier = ">=7.2.2" },
|
||||
{ name = "psutils", specifier = ">=3.3.17" },
|
||||
{ name = "pydantic", specifier = ">=2.13.4" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
@@ -91,6 +97,56 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psutil"
|
||||
version = "7.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psutils"
|
||||
version = "3.3.17"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "puremagic" },
|
||||
{ name = "pypdf" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a0/6b/735ab226ab8e2ee6b99182312c7346a2e4bd3e825cfdf127f22ce75e853f/psutils-3.3.17.tar.gz", hash = "sha256:3ff76cc9f9fb535ec553d1591de56d6dbaa0d9f4df86778f6a49731ebd764cdf", size = 1255066, upload-time = "2026-09-07T13:15:05.562Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/96/c6/84c07085ebc0130e1bc7f1957e10ad42ea53f2f65177e107a5c76323b78c/psutils-3.3.17-py3-none-any.whl", hash = "sha256:de0289f2eac5966c2481a02cfa6eed0dc0f8e67115356eb44dbab429610f5970", size = 55328, upload-time = "2026-09-07T13:15:02.882Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "puremagic"
|
||||
version = "2.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/24/74/ce5987ab9b8aec4ced06e2723ebb604205c9eb58abdad91453da93166380/puremagic-2.2.0.tar.gz", hash = "sha256:eb4bddf07c177c4b434554b92165b67449f5a51e152b976202d6254498810eef", size = 1189752, upload-time = "2026-04-08T01:39:55.562Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/95/81/314320aeffd88dadeac553ff9eb10f54507ab41deccd0c69f6221d254a0a/puremagic-2.2.0-py3-none-any.whl", hash = "sha256:c4f7ed7307f056c787199acfda839555921be1df13abba61e8e6db0c787ae1d0", size = 71971, upload-time = "2026-04-08T01:39:54.169Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.13.4"
|
||||
@@ -171,6 +227,15 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/7e/a72dd26f3b0f4f2bf1dd8923c85f7ceb43172af56d63c7383eb62b332364/pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176", size = 1231151, upload-time = "2026-03-29T13:29:30.038Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pypdf"
|
||||
version = "6.19.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1f/ac/63d71aaedb59acbcdef491e6ca6469165e3771c9c74358204818fd9bc5a6/pypdf-6.19.0.tar.gz", hash = "sha256:bbc43aca292369ccc6cbc8a921991ecf2538a3587ab5a116eff06c321d647155", size = 7033266, upload-time = "2026-09-16T09:32:05.946Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/2c/c43c03eaf630435f023f1dc61ec4a4a78951ad5530a62c71cc89bde307b7/pypdf-6.19.0-py3-none-any.whl", hash = "sha256:7e5d6e730e7dae87d560a2cee218b852f6498c8be61966f3cd02ead971e48d14", size = 395480, upload-time = "2026-09-16T09:32:04.087Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "9.1.1"
|
||||
|
||||
Reference in new issue
Block a user