Spaces:
Running
Running
Update mew_log/profile_utils.py
Browse files- mew_log/profile_utils.py +194 -194
mew_log/profile_utils.py
CHANGED
@@ -1,194 +1,194 @@
|
|
1 |
-
import time
|
2 |
-
|
3 |
-
from
|
4 |
-
from
|
5 |
-
from
|
6 |
-
from
|
7 |
-
|
8 |
-
|
9 |
-
time_color = ''
|
10 |
-
|
11 |
-
# helper funcs
|
12 |
-
class ProfileSection:
|
13 |
-
Registry = {} # Class Variable
|
14 |
-
|
15 |
-
def __init__(self, newMsg=None, enable=True, do_print=False):
|
16 |
-
self.msg = newMsg if newMsg else get_prev_caller_info()
|
17 |
-
self.enable = enable
|
18 |
-
self.startTime = 0.0
|
19 |
-
self.endTime = 0.0
|
20 |
-
self.elapsedTime = 0.0
|
21 |
-
self.totalTime = 0.0
|
22 |
-
self.avgTime = 0.0
|
23 |
-
self.numCalls = 0
|
24 |
-
self.do_print = do_print
|
25 |
-
if self.msg in ProfileSection.Registry:
|
26 |
-
p = ProfileSection.Registry[self.msg]
|
27 |
-
self.__dict__ = p.__dict__
|
28 |
-
self.numCalls += 1
|
29 |
-
else:
|
30 |
-
self.numCalls += 1
|
31 |
-
|
32 |
-
if (self.enable):
|
33 |
-
self.start()
|
34 |
-
|
35 |
-
def __del__(self):
|
36 |
-
if (self.enable):
|
37 |
-
self.stop()
|
38 |
-
|
39 |
-
def __enter__(self):
|
40 |
-
# if self.enable:
|
41 |
-
self.start()
|
42 |
-
|
43 |
-
return self
|
44 |
-
|
45 |
-
def __exit__(self, exc_type, exc_value, traceback):
|
46 |
-
# if self.enable:
|
47 |
-
self.stop()
|
48 |
-
|
49 |
-
def start(self):
|
50 |
-
self.startTime = time.time()
|
51 |
-
# if self.do_print : log_info(str(self))
|
52 |
-
|
53 |
-
def stop(self):
|
54 |
-
self.endTime = time.time()
|
55 |
-
self.update_stats()
|
56 |
-
stopMsg = str(self)
|
57 |
-
|
58 |
-
p = create_or_get_profile(self.msg)
|
59 |
-
p.__dict__.update(self.__dict__)
|
60 |
-
if self.do_print: log_info(str(p))
|
61 |
-
|
62 |
-
# st.toast(stopMsg)
|
63 |
-
return stopMsg
|
64 |
-
|
65 |
-
def update_stats(self):
|
66 |
-
self.elapsedTime = self.endTime - self.startTime
|
67 |
-
self.totalTime += self.elapsedTime
|
68 |
-
self.avgTime = self.totalTime / float(self.numCalls)
|
69 |
-
|
70 |
-
def __str__(self, use_color=True):
|
71 |
-
msg_str = self.msg #ansi_color_str(self.msg, fg='green') # Green color for message
|
72 |
-
elapsed_time_str = make_time_str('elapsed', self.elapsedTime)
|
73 |
-
total_time_str = make_time_str('total', self.totalTime)
|
74 |
-
avg_time_str = make_time_str('avg', self.avgTime)
|
75 |
-
calls_str = f'calls={self.numCalls}'
|
76 |
-
if use_color:
|
77 |
-
elapsed_time_str = ansi_color_str(elapsed_time_str, fg='bright_cyan') # Cyan color for elapsed time
|
78 |
-
total_time_str = ansi_color_str(total_time_str, fg='bright_cyan') # Cyan color for total time
|
79 |
-
avg_time_str = ansi_color_str(avg_time_str, fg='bright_cyan') # Cyan color for average time
|
80 |
-
calls_str = ansi_color_str(calls_str, fg='yellow') # Cyan color for calls information
|
81 |
-
|
82 |
-
return f"{msg_str} ~ Elapsed Time: {elapsed_time_str} | Total Time: {total_time_str} | Avg Time: {avg_time_str} | {calls_str}"
|
83 |
-
|
84 |
-
|
85 |
-
from functools import wraps
|
86 |
-
from threading import Thread
|
87 |
-
from rich.progress import Progress, BarColumn, TextColumn, TimeRemainingColumn, TaskProgressColumn
|
88 |
-
from rich.console import Console
|
89 |
-
from rich.style import Style
|
90 |
-
from rich.panel import Panel
|
91 |
-
|
92 |
-
|
93 |
-
def profile_function(func):
|
94 |
-
"""
|
95 |
-
Decorator to track the progress of a function with a spinner.
|
96 |
-
The decorated function should not require explicit progress updates.
|
97 |
-
"""
|
98 |
-
@wraps(func)
|
99 |
-
def wrapper(*args, **kwargs):
|
100 |
-
profile_section = ProfileSection(func.__name__, enable=True, do_print=False)
|
101 |
-
console = Console()
|
102 |
-
with LogSpinner(func.__name__):
|
103 |
-
with profile_section:
|
104 |
-
result = func(*args, **kwargs)
|
105 |
-
|
106 |
-
#profile_section.stop()
|
107 |
-
# Display timing information using rich
|
108 |
-
panel = Panel.fit(
|
109 |
-
f"[bold green]{profile_section.msg}[/bold green]\n"
|
110 |
-
f"[cyan]Elapsed Time:[/cyan] {make_time_str('elapsed', profile_section.elapsedTime)}\n"
|
111 |
-
f"[cyan]Total Time:[/cyan] {make_time_str('total', profile_section.totalTime)}\n"
|
112 |
-
f"[cyan]Avg Time:[/cyan] {make_time_str('avg', profile_section.avgTime)}\n"
|
113 |
-
f"[yellow]Calls:[/yellow] {profile_section.numCalls}",
|
114 |
-
title="Profile Report",
|
115 |
-
border_style="bright_blue"
|
116 |
-
)
|
117 |
-
console.print(panel)
|
118 |
-
#print(str(profile_section))
|
119 |
-
|
120 |
-
|
121 |
-
return result
|
122 |
-
return wrapper
|
123 |
-
|
124 |
-
|
125 |
-
def make_time_str(msg, value):
|
126 |
-
# do something fancy
|
127 |
-
value, time_unit = (value / 60, 'min') if value >= 60 else (value * 1000, 'ms') if value < 0.01 else (value, 's')
|
128 |
-
return f"{msg}={int(value) if value % 1 == 0 else value:.2f} {time_unit}"
|
129 |
-
|
130 |
-
|
131 |
-
def create_or_get_profile(key, enable=False, do_print=False):
|
132 |
-
if key not in ProfileSection.Registry:
|
133 |
-
ProfileSection.Registry[key] = ProfileSection(key, enable, do_print)
|
134 |
-
return ProfileSection.Registry[key]
|
135 |
-
|
136 |
-
|
137 |
-
def profile_start(msg, enable=True, do_print=False):
|
138 |
-
p = create_or_get_profile(msg, enable, do_print)
|
139 |
-
if not enable: p.start()
|
140 |
-
|
141 |
-
|
142 |
-
def profile_stop(msg):
|
143 |
-
if key in ProfileSection.Registry:
|
144 |
-
create_or_get_profile(msg).stop()
|
145 |
-
|
146 |
-
|
147 |
-
def get_profile_registry():
|
148 |
-
return ProfileSection.Registry
|
149 |
-
|
150 |
-
from loguru import logger
|
151 |
-
|
152 |
-
|
153 |
-
def get_profile_reports():
|
154 |
-
reports = [value for value in ProfileSection.Registry.values()]
|
155 |
-
reports.sort(key=lambda x: (x.totalTime, x.avgTime), reverse=True)
|
156 |
-
return reports
|
157 |
-
|
158 |
-
def log_profile_registry(use_color=True):
|
159 |
-
formatted_output = format_profile_registry(use_color=use_color)
|
160 |
-
print(formatted_output)
|
161 |
-
#logger.info(formatted_output)
|
162 |
-
#return formatted_output
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
def allow_curly_braces(original_string):
|
167 |
-
escaped_string = original_string.replace("{", "{{").replace("}", "}}")
|
168 |
-
#print("Escaped String:", escaped_string) # Debug output
|
169 |
-
return escaped_string
|
170 |
-
|
171 |
-
def format_profile_registry(use_color=True):
|
172 |
-
reports = get_profile_reports()
|
173 |
-
out_str = []
|
174 |
-
|
175 |
-
out_str.append('=== Profile Reports ===\n')
|
176 |
-
|
177 |
-
for report in reports:
|
178 |
-
out_str.append(str(report)+'\n')
|
179 |
-
|
180 |
-
out_str.append('===>_<===\n')
|
181 |
-
return ''.join(out_str)
|
182 |
-
|
183 |
-
|
184 |
-
# import random
|
185 |
-
|
186 |
-
# def do_this(y):
|
187 |
-
# p = ProfileSection("do_this", True) #only way to use the auto destruct method
|
188 |
-
# x = random.randint(0, (y+1)*2)
|
189 |
-
# print(f'do_this: {x} - {y}')
|
190 |
-
|
191 |
-
# for index in range(1000):
|
192 |
-
# do_this(index)
|
193 |
-
|
194 |
-
# log_profile_registry()
|
|
|
1 |
+
import time
|
2 |
+
|
3 |
+
from ansi_utils import ansi_color_str
|
4 |
+
from attr_utils import get_prev_caller_info
|
5 |
+
from log_utils import log_info, LogSpinner
|
6 |
+
from table_utils import format_table
|
7 |
+
|
8 |
+
|
9 |
+
time_color = ''
|
10 |
+
|
11 |
+
# helper funcs
|
12 |
+
class ProfileSection:
|
13 |
+
Registry = {} # Class Variable
|
14 |
+
|
15 |
+
def __init__(self, newMsg=None, enable=True, do_print=False):
|
16 |
+
self.msg = newMsg if newMsg else get_prev_caller_info()
|
17 |
+
self.enable = enable
|
18 |
+
self.startTime = 0.0
|
19 |
+
self.endTime = 0.0
|
20 |
+
self.elapsedTime = 0.0
|
21 |
+
self.totalTime = 0.0
|
22 |
+
self.avgTime = 0.0
|
23 |
+
self.numCalls = 0
|
24 |
+
self.do_print = do_print
|
25 |
+
if self.msg in ProfileSection.Registry:
|
26 |
+
p = ProfileSection.Registry[self.msg]
|
27 |
+
self.__dict__ = p.__dict__
|
28 |
+
self.numCalls += 1
|
29 |
+
else:
|
30 |
+
self.numCalls += 1
|
31 |
+
|
32 |
+
if (self.enable):
|
33 |
+
self.start()
|
34 |
+
|
35 |
+
def __del__(self):
|
36 |
+
if (self.enable):
|
37 |
+
self.stop()
|
38 |
+
|
39 |
+
def __enter__(self):
|
40 |
+
# if self.enable:
|
41 |
+
self.start()
|
42 |
+
|
43 |
+
return self
|
44 |
+
|
45 |
+
def __exit__(self, exc_type, exc_value, traceback):
|
46 |
+
# if self.enable:
|
47 |
+
self.stop()
|
48 |
+
|
49 |
+
def start(self):
|
50 |
+
self.startTime = time.time()
|
51 |
+
# if self.do_print : log_info(str(self))
|
52 |
+
|
53 |
+
def stop(self):
|
54 |
+
self.endTime = time.time()
|
55 |
+
self.update_stats()
|
56 |
+
stopMsg = str(self)
|
57 |
+
|
58 |
+
p = create_or_get_profile(self.msg)
|
59 |
+
p.__dict__.update(self.__dict__)
|
60 |
+
if self.do_print: log_info(str(p))
|
61 |
+
|
62 |
+
# st.toast(stopMsg)
|
63 |
+
return stopMsg
|
64 |
+
|
65 |
+
def update_stats(self):
|
66 |
+
self.elapsedTime = self.endTime - self.startTime
|
67 |
+
self.totalTime += self.elapsedTime
|
68 |
+
self.avgTime = self.totalTime / float(self.numCalls)
|
69 |
+
|
70 |
+
def __str__(self, use_color=True):
|
71 |
+
msg_str = self.msg #ansi_color_str(self.msg, fg='green') # Green color for message
|
72 |
+
elapsed_time_str = make_time_str('elapsed', self.elapsedTime)
|
73 |
+
total_time_str = make_time_str('total', self.totalTime)
|
74 |
+
avg_time_str = make_time_str('avg', self.avgTime)
|
75 |
+
calls_str = f'calls={self.numCalls}'
|
76 |
+
if use_color:
|
77 |
+
elapsed_time_str = ansi_color_str(elapsed_time_str, fg='bright_cyan') # Cyan color for elapsed time
|
78 |
+
total_time_str = ansi_color_str(total_time_str, fg='bright_cyan') # Cyan color for total time
|
79 |
+
avg_time_str = ansi_color_str(avg_time_str, fg='bright_cyan') # Cyan color for average time
|
80 |
+
calls_str = ansi_color_str(calls_str, fg='yellow') # Cyan color for calls information
|
81 |
+
|
82 |
+
return f"{msg_str} ~ Elapsed Time: {elapsed_time_str} | Total Time: {total_time_str} | Avg Time: {avg_time_str} | {calls_str}"
|
83 |
+
|
84 |
+
|
85 |
+
from functools import wraps
|
86 |
+
from threading import Thread
|
87 |
+
from rich.progress import Progress, BarColumn, TextColumn, TimeRemainingColumn, TaskProgressColumn
|
88 |
+
from rich.console import Console
|
89 |
+
from rich.style import Style
|
90 |
+
from rich.panel import Panel
|
91 |
+
|
92 |
+
|
93 |
+
def profile_function(func):
|
94 |
+
"""
|
95 |
+
Decorator to track the progress of a function with a spinner.
|
96 |
+
The decorated function should not require explicit progress updates.
|
97 |
+
"""
|
98 |
+
@wraps(func)
|
99 |
+
def wrapper(*args, **kwargs):
|
100 |
+
profile_section = ProfileSection(func.__name__, enable=True, do_print=False)
|
101 |
+
console = Console()
|
102 |
+
with LogSpinner(func.__name__):
|
103 |
+
with profile_section:
|
104 |
+
result = func(*args, **kwargs)
|
105 |
+
|
106 |
+
#profile_section.stop()
|
107 |
+
# Display timing information using rich
|
108 |
+
panel = Panel.fit(
|
109 |
+
f"[bold green]{profile_section.msg}[/bold green]\n"
|
110 |
+
f"[cyan]Elapsed Time:[/cyan] {make_time_str('elapsed', profile_section.elapsedTime)}\n"
|
111 |
+
f"[cyan]Total Time:[/cyan] {make_time_str('total', profile_section.totalTime)}\n"
|
112 |
+
f"[cyan]Avg Time:[/cyan] {make_time_str('avg', profile_section.avgTime)}\n"
|
113 |
+
f"[yellow]Calls:[/yellow] {profile_section.numCalls}",
|
114 |
+
title="Profile Report",
|
115 |
+
border_style="bright_blue"
|
116 |
+
)
|
117 |
+
console.print(panel)
|
118 |
+
#print(str(profile_section))
|
119 |
+
|
120 |
+
|
121 |
+
return result
|
122 |
+
return wrapper
|
123 |
+
|
124 |
+
|
125 |
+
def make_time_str(msg, value):
|
126 |
+
# do something fancy
|
127 |
+
value, time_unit = (value / 60, 'min') if value >= 60 else (value * 1000, 'ms') if value < 0.01 else (value, 's')
|
128 |
+
return f"{msg}={int(value) if value % 1 == 0 else value:.2f} {time_unit}"
|
129 |
+
|
130 |
+
|
131 |
+
def create_or_get_profile(key, enable=False, do_print=False):
|
132 |
+
if key not in ProfileSection.Registry:
|
133 |
+
ProfileSection.Registry[key] = ProfileSection(key, enable, do_print)
|
134 |
+
return ProfileSection.Registry[key]
|
135 |
+
|
136 |
+
|
137 |
+
def profile_start(msg, enable=True, do_print=False):
|
138 |
+
p = create_or_get_profile(msg, enable, do_print)
|
139 |
+
if not enable: p.start()
|
140 |
+
|
141 |
+
|
142 |
+
def profile_stop(msg):
|
143 |
+
if key in ProfileSection.Registry:
|
144 |
+
create_or_get_profile(msg).stop()
|
145 |
+
|
146 |
+
|
147 |
+
def get_profile_registry():
|
148 |
+
return ProfileSection.Registry
|
149 |
+
|
150 |
+
from loguru import logger
|
151 |
+
|
152 |
+
|
153 |
+
def get_profile_reports():
|
154 |
+
reports = [value for value in ProfileSection.Registry.values()]
|
155 |
+
reports.sort(key=lambda x: (x.totalTime, x.avgTime), reverse=True)
|
156 |
+
return reports
|
157 |
+
|
158 |
+
def log_profile_registry(use_color=True):
|
159 |
+
formatted_output = format_profile_registry(use_color=use_color)
|
160 |
+
print(formatted_output)
|
161 |
+
#logger.info(formatted_output)
|
162 |
+
#return formatted_output
|
163 |
+
|
164 |
+
|
165 |
+
|
166 |
+
def allow_curly_braces(original_string):
|
167 |
+
escaped_string = original_string.replace("{", "{{").replace("}", "}}")
|
168 |
+
#print("Escaped String:", escaped_string) # Debug output
|
169 |
+
return escaped_string
|
170 |
+
|
171 |
+
def format_profile_registry(use_color=True):
|
172 |
+
reports = get_profile_reports()
|
173 |
+
out_str = []
|
174 |
+
|
175 |
+
out_str.append('=== Profile Reports ===\n')
|
176 |
+
|
177 |
+
for report in reports:
|
178 |
+
out_str.append(str(report)+'\n')
|
179 |
+
|
180 |
+
out_str.append('===>_<===\n')
|
181 |
+
return ''.join(out_str)
|
182 |
+
|
183 |
+
|
184 |
+
# import random
|
185 |
+
|
186 |
+
# def do_this(y):
|
187 |
+
# p = ProfileSection("do_this", True) #only way to use the auto destruct method
|
188 |
+
# x = random.randint(0, (y+1)*2)
|
189 |
+
# print(f'do_this: {x} - {y}')
|
190 |
+
|
191 |
+
# for index in range(1000):
|
192 |
+
# do_this(index)
|
193 |
+
|
194 |
+
# log_profile_registry()
|