Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
singlestore-labs
GitHub Repository: singlestore-labs/singlestoredb-python
Path: blob/main/singlestoredb/functions/ext/timer.py
469 views
1
import json
2
import time
3
from typing import Any
4
from typing import Dict
5
from typing import Optional
6
7
8
class RoundedFloatEncoder(json.JSONEncoder):
9
10
def encode(self, obj: Any) -> str:
11
if isinstance(obj, dict):
12
return '{' + ', '.join(
13
f'"{k}": {self._format_value(v)}'
14
for k, v in obj.items()
15
) + '}'
16
return super().encode(obj)
17
18
def _format_value(self, value: Any) -> str:
19
if isinstance(value, float):
20
return f'{value:.2f}'
21
return json.dumps(value)
22
23
24
class Timer:
25
"""
26
Timer context manager that supports nested timing using a stack.
27
28
Example
29
-------
30
timer = Timer()
31
32
with timer('total'):
33
with timer('receive_data'):
34
time.sleep(0.1)
35
with timer('parse_input'):
36
time.sleep(0.2)
37
with timer('call_function'):
38
with timer('inner_operation'):
39
time.sleep(0.05)
40
time.sleep(0.3)
41
42
print(timer.metrics)
43
# {'receive_data': 0.1, 'parse_input': 0.2, 'inner_operation': 0.05,
44
# 'call_function': 0.35, 'total': 0.65}
45
46
"""
47
48
def __init__(self, **kwargs: Any) -> None:
49
self.metadata: Dict[str, Any] = kwargs
50
self.metrics: Dict[str, float] = dict()
51
self.entries: Dict[str, float] = dict()
52
self._current_key: Optional[str] = None
53
self.start_time = time.perf_counter()
54
55
def __call__(self, key: str) -> 'Timer':
56
self._current_key = key
57
return self
58
59
def __enter__(self) -> 'Timer':
60
if self._current_key is None:
61
raise ValueError(
62
"No key specified. Use timer('key_name') as context manager.",
63
)
64
self.entries[self._current_key] = time.perf_counter()
65
return self
66
67
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
68
key = self._current_key
69
if key and key in self.entries:
70
start = self.entries.pop(key)
71
elapsed = time.perf_counter() - start
72
self.metrics[key] = elapsed
73
self._current_key = None
74
75
async def __aenter__(self) -> 'Timer':
76
return self.__enter__()
77
78
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
79
self.__exit__(exc_type, exc_val, exc_tb)
80
81
def reset(self) -> None:
82
self.metrics.clear()
83
self.entries.clear()
84
self._current_key = None
85
86
def finish(self) -> Dict[str, Any]:
87
"""Finish the current timing context and store the elapsed time."""
88
self.metrics['total'] = time.perf_counter() - self.start_time
89
return dict(type='function_metrics', **self.metadata, **self.metrics)
90
91