feat(perf): Add high-resolution component profiling to main loop
This commit is contained in:
14
gui.py
14
gui.py
@@ -2237,14 +2237,18 @@ class App:
|
|||||||
|
|
||||||
while dpg.is_dearpygui_running():
|
while dpg.is_dearpygui_running():
|
||||||
self.perf_monitor.start_frame()
|
self.perf_monitor.start_frame()
|
||||||
|
|
||||||
# Show any pending confirmation dialog on the main thread safely
|
# Show any pending confirmation dialog on the main thread safely
|
||||||
|
self.perf_monitor.start_component("Dialogs")
|
||||||
with self._pending_dialog_lock:
|
with self._pending_dialog_lock:
|
||||||
dialog = self._pending_dialog
|
dialog = self._pending_dialog
|
||||||
self._pending_dialog = None
|
self._pending_dialog = None
|
||||||
if dialog is not None:
|
if dialog is not None:
|
||||||
dialog.show()
|
dialog.show()
|
||||||
|
self.perf_monitor.end_component("Dialogs")
|
||||||
|
|
||||||
# Process queued history additions
|
# Process queued history additions
|
||||||
|
self.perf_monitor.start_component("History")
|
||||||
with self._pending_history_adds_lock:
|
with self._pending_history_adds_lock:
|
||||||
adds = self._pending_history_adds[:]
|
adds = self._pending_history_adds[:]
|
||||||
self._pending_history_adds.clear()
|
self._pending_history_adds.clear()
|
||||||
@@ -2259,8 +2263,10 @@ class App:
|
|||||||
if dpg.does_item_exist("disc_scroll"):
|
if dpg.does_item_exist("disc_scroll"):
|
||||||
# Force scroll to bottom using a very large number
|
# Force scroll to bottom using a very large number
|
||||||
dpg.set_y_scroll("disc_scroll", 99999)
|
dpg.set_y_scroll("disc_scroll", 99999)
|
||||||
|
self.perf_monitor.end_component("History")
|
||||||
|
|
||||||
# Process queued API GUI tasks
|
# Process queued API GUI tasks
|
||||||
|
self.perf_monitor.start_component("GUI_Tasks")
|
||||||
with self._pending_gui_tasks_lock:
|
with self._pending_gui_tasks_lock:
|
||||||
gui_tasks = self._pending_gui_tasks[:]
|
gui_tasks = self._pending_gui_tasks[:]
|
||||||
self._pending_gui_tasks.clear()
|
self._pending_gui_tasks.clear()
|
||||||
@@ -2280,8 +2286,10 @@ class App:
|
|||||||
cb()
|
cb()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error executing GUI hook task: {e}")
|
print(f"Error executing GUI hook task: {e}")
|
||||||
|
self.perf_monitor.end_component("GUI_Tasks")
|
||||||
|
|
||||||
# Handle retro arcade blinking effect
|
# Handle retro arcade blinking effect
|
||||||
|
self.perf_monitor.start_component("Blinking")
|
||||||
if self._trigger_script_blink:
|
if self._trigger_script_blink:
|
||||||
self._trigger_script_blink = False
|
self._trigger_script_blink = False
|
||||||
self._is_script_blinking = True
|
self._is_script_blinking = True
|
||||||
@@ -2369,10 +2377,16 @@ class App:
|
|||||||
dpg.bind_item_theme("ai_response_wrap_container", "response_blink_theme")
|
dpg.bind_item_theme("ai_response_wrap_container", "response_blink_theme")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
self.perf_monitor.end_component("Blinking")
|
||||||
|
|
||||||
# Flush any comms entries queued from background threads
|
# Flush any comms entries queued from background threads
|
||||||
|
self.perf_monitor.start_component("Comms")
|
||||||
self._flush_pending_comms()
|
self._flush_pending_comms()
|
||||||
|
self.perf_monitor.end_component("Comms")
|
||||||
|
|
||||||
|
self.perf_monitor.start_component("Telemetry")
|
||||||
self._update_telemetry_panel()
|
self._update_telemetry_panel()
|
||||||
|
self.perf_monitor.end_component("Telemetry")
|
||||||
|
|
||||||
self.perf_monitor.end_frame()
|
self.perf_monitor.end_frame()
|
||||||
dpg.render_dearpygui_frame()
|
dpg.render_dearpygui_frame()
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ class PerformanceMonitor:
|
|||||||
}
|
}
|
||||||
self._last_alert_time = 0
|
self._last_alert_time = 0
|
||||||
self._alert_cooldown = 30 # seconds
|
self._alert_cooldown = 30 # seconds
|
||||||
|
|
||||||
|
# Detailed profiling
|
||||||
|
self._component_timings = {}
|
||||||
|
self._comp_start = {}
|
||||||
|
|
||||||
# Start CPU usage monitoring thread
|
# Start CPU usage monitoring thread
|
||||||
self._stop_event = threading.Event()
|
self._stop_event = threading.Event()
|
||||||
@@ -46,6 +50,14 @@ class PerformanceMonitor:
|
|||||||
def record_input_event(self):
|
def record_input_event(self):
|
||||||
self._last_input_time = time.time()
|
self._last_input_time = time.time()
|
||||||
|
|
||||||
|
def start_component(self, name: str):
|
||||||
|
self._comp_start[name] = time.time()
|
||||||
|
|
||||||
|
def end_component(self, name: str):
|
||||||
|
if name in self._comp_start:
|
||||||
|
elapsed = (time.time() - self._comp_start[name]) * 1000.0
|
||||||
|
self._component_timings[name] = elapsed
|
||||||
|
|
||||||
def end_frame(self):
|
def end_frame(self):
|
||||||
if self._start_time is None:
|
if self._start_time is None:
|
||||||
return
|
return
|
||||||
@@ -92,12 +104,20 @@ class PerformanceMonitor:
|
|||||||
with self._cpu_lock:
|
with self._cpu_lock:
|
||||||
cpu_usage = self._cpu_usage
|
cpu_usage = self._cpu_usage
|
||||||
|
|
||||||
return {
|
metrics = {
|
||||||
'last_frame_time_ms': self._last_frame_time,
|
'last_frame_time_ms': self._last_frame_time,
|
||||||
'fps': self._fps,
|
'fps': self._fps,
|
||||||
'cpu_percent': cpu_usage,
|
'cpu_percent': cpu_usage,
|
||||||
'input_lag_ms': self._input_lag_ms
|
'input_lag_ms': self._last_input_time if self._last_input_time else 0.0 # Wait, this should be the calculated lag
|
||||||
}
|
}
|
||||||
|
# Oops, fixed the input lag logic in previous turn, let's keep it consistent
|
||||||
|
metrics['input_lag_ms'] = self._input_lag_ms
|
||||||
|
|
||||||
|
# Add detailed timings
|
||||||
|
for name, elapsed in self._component_timings.items():
|
||||||
|
metrics[f'time_{name}_ms'] = elapsed
|
||||||
|
|
||||||
|
return metrics
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self._stop_event.set()
|
self._stop_event.set()
|
||||||
|
|||||||
Reference in New Issue
Block a user