pelutils 4.3.1__tar.gz → 4.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pelutils-4.3.1 → pelutils-4.4.0}/PKG-INFO +1 -1
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/__version__.py +1 -1
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/ticktock/__init__.py +2 -2
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/ticktock/_ticktock.py +52 -7
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils.egg-info/PKG-INFO +1 -1
- {pelutils-4.3.1 → pelutils-4.4.0}/MANIFEST.in +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/README.md +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/array/blob.c +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/array/blob.h +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/array/unique.c +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/array/unique.h +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/deque/deque.c +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/deque/deque.h +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/hashmap/LICENSE +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/hashmap/hashmap.c +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/hashmap/hashmap.h +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/pelutils.c +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_c/types.h +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_entry_points/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/_entry_points/linecounter.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/array/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/array/_blob.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/array/_unique.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/array/_utils.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/job_parser/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/job_parser/_job_parser.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/job_parser/_structs.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/legacy/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/legacy/v3/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/legacy/v3/_datastorage.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/logging/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/logging/_logger.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/logging/_rich_string.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/logging/_rotate.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/misc/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/misc/_conditional_import.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/misc/_files.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/misc/_git.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/misc/_misc.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/misc/_platform.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/misc/_table.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/plots/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/plots/_figure.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/plots/_histogram.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/plots/_utils.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/py.typed +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/serialization/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/serialization/_jsonl.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/serialization/_pretty_json.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/serialization/_universal_json_model.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/stats/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/stats/_distributions.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/stats/_stats.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/tests/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/tests/_tests.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/types/__init__.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils/types/_types.py +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils.egg-info/SOURCES.txt +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils.egg-info/dependency_links.txt +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils.egg-info/entry_points.txt +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils.egg-info/requires.txt +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/pelutils.egg-info/top_level.txt +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/setup.cfg +0 -0
- {pelutils-4.3.1 → pelutils-4.4.0}/setup.py +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# Do not put anything else in this file
|
|
2
|
-
__version__ = "4.
|
|
2
|
+
__version__ = "4.4.0"
|
|
@@ -37,6 +37,6 @@ periodic tasks, and ``fuse``/``fuse_multiple`` for combining results across
|
|
|
37
37
|
processes.
|
|
38
38
|
"""
|
|
39
39
|
|
|
40
|
-
from ._ticktock import TT, Profile, TickTock, TickTockException
|
|
40
|
+
from ._ticktock import TT, Profile, TickTock, TickTockException, get_active_ticktock
|
|
41
41
|
|
|
42
|
-
__all__ = ("TT", "Profile", "TickTock", "TickTockException")
|
|
42
|
+
__all__ = ("TT", "Profile", "TickTock", "TickTockException", "get_active_ticktock")
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
import threading
|
|
1
3
|
import warnings
|
|
2
4
|
from collections.abc import Hashable, Iterable, Iterator, Sequence
|
|
3
5
|
from contextlib import contextmanager
|
|
4
6
|
from copy import deepcopy
|
|
5
|
-
from threading import current_thread
|
|
6
7
|
from time import perf_counter
|
|
7
8
|
from typing import TypeAlias, TypeVar, cast
|
|
8
9
|
|
|
@@ -23,6 +24,20 @@ _time_units: tuple[_TimeUnit, ...] = (
|
|
|
23
24
|
|
|
24
25
|
T = TypeVar("T")
|
|
25
26
|
|
|
27
|
+
_lock = threading.RLock()
|
|
28
|
+
_active_ticktocks: "dict[int, TickTock]" = dict()
|
|
29
|
+
_ids = itertools.count()
|
|
30
|
+
_ids_lock = threading.RLock()
|
|
31
|
+
_local_thread = threading.local()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _get_thread_uid() -> int:
|
|
35
|
+
"""Return a stable, program-lifetime-unique ID for the calling thread."""
|
|
36
|
+
if not hasattr(_local_thread, "__ticktock_uid__"):
|
|
37
|
+
with _ids_lock:
|
|
38
|
+
_local_thread.__ticktock_uid__ = next(_ids)
|
|
39
|
+
return _local_thread.__ticktock_uid__
|
|
40
|
+
|
|
26
41
|
|
|
27
42
|
def _get_smallest_suitable_unit(duration_s: float) -> _TimeUnit:
|
|
28
43
|
"""Return the smallest unit for which the duration is at least the same size as the unit."""
|
|
@@ -160,8 +175,8 @@ class TickTock:
|
|
|
160
175
|
self._profile_stack: list[Profile] = list() # LIFO stack of active profiles
|
|
161
176
|
self._root_profiles: list[Profile] = list() # Top level profiles
|
|
162
177
|
|
|
163
|
-
self._thread_name = current_thread().name
|
|
164
|
-
self._thread_id =
|
|
178
|
+
self._thread_name = threading.current_thread().name
|
|
179
|
+
self._thread_id = _get_thread_uid()
|
|
165
180
|
|
|
166
181
|
def tick(self, key: Hashable = None):
|
|
167
182
|
"""Start a timer identified by an optional hashable key."""
|
|
@@ -244,10 +259,10 @@ class TickTock:
|
|
|
244
259
|
self._end_profile()
|
|
245
260
|
|
|
246
261
|
def _warn_if_wrong_thread(self, *, stacklevel: int):
|
|
247
|
-
if self._thread_id !=
|
|
262
|
+
if self._thread_id != _get_thread_uid():
|
|
248
263
|
warnings.warn(
|
|
249
264
|
f"This TickTock instance was created in the {self._thread_name} thread but profiling was started in "
|
|
250
|
-
+ f"{current_thread().name}. Profiling is NOT designed to deal with multiple threads. Instead, create a "
|
|
265
|
+
+ f"{threading.current_thread().name}. Profiling is NOT designed to deal with multiple threads. Instead, create a "
|
|
251
266
|
+ "TickTock instance for each thread requiring profiling.",
|
|
252
267
|
stacklevel=stacklevel,
|
|
253
268
|
)
|
|
@@ -393,8 +408,8 @@ class TickTock:
|
|
|
393
408
|
raise ValueError("Some TickTocks are the same instance, which is not allowed")
|
|
394
409
|
for tt in tts[1:]:
|
|
395
410
|
ticktock.fuse(tt)
|
|
396
|
-
ticktock._thread_name = current_thread().name
|
|
397
|
-
ticktock._thread_id =
|
|
411
|
+
ticktock._thread_name = threading.current_thread().name
|
|
412
|
+
ticktock._thread_id = _get_thread_uid()
|
|
398
413
|
return ticktock
|
|
399
414
|
|
|
400
415
|
@staticmethod
|
|
@@ -446,5 +461,35 @@ class TickTock:
|
|
|
446
461
|
"""Return True if any profiling has been performed."""
|
|
447
462
|
return len(self._root_profiles) > 0
|
|
448
463
|
|
|
464
|
+
@contextmanager
|
|
465
|
+
def as_active(self):
|
|
466
|
+
"""Set the ``TickTock`` instance as the active instance in the current thread.
|
|
467
|
+
|
|
468
|
+
It can then be retrieved with :func:`get_active_ticktock`.
|
|
469
|
+
"""
|
|
470
|
+
current_thread_id = _get_thread_uid()
|
|
471
|
+
with _lock:
|
|
472
|
+
if current_thread_id in _active_ticktocks:
|
|
473
|
+
raise TickTockException(f"An active TickTock instance has already been set in thread {threading.current_thread().name}")
|
|
474
|
+
_active_ticktocks[current_thread_id] = self
|
|
475
|
+
try:
|
|
476
|
+
yield
|
|
477
|
+
finally:
|
|
478
|
+
with _lock:
|
|
479
|
+
del _active_ticktocks[current_thread_id]
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
def get_active_ticktock() -> TickTock:
|
|
483
|
+
"""Return the active ``TickTock`` instance in the current thread (as set by :meth:`TickTock.as_active`).
|
|
484
|
+
|
|
485
|
+
If no active ``TickTock`` is set, a new ``TickTock`` instance is returned.
|
|
486
|
+
This allows normal profiling usage without having to care if it's actually used or not.
|
|
487
|
+
"""
|
|
488
|
+
with _lock:
|
|
489
|
+
ticktock = _active_ticktocks.get(_get_thread_uid())
|
|
490
|
+
return ticktock if ticktock is not None else TickTock()
|
|
491
|
+
|
|
449
492
|
|
|
493
|
+
# Globally accessible default instance
|
|
494
|
+
# It suffices to use this for most cases
|
|
450
495
|
TT = TickTock()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|