""" Test script per verificare le ottimizzazioni del sistema di logging. Usage: $env:PYTHONPATH='C:\src\____GitProjects\target_simulator' python tools/test_logging_performance.py """ import time import logging import tkinter as tk from tkinter.scrolledtext import ScrolledText import sys import os # Add project root to path sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from target_simulator.utils.logger import setup_basic_logging, add_tkinter_handler, get_logger from target_simulator.config import LOGGING_CONFIG def stress_test_logging(logger, num_messages=1000, delay_ms=0): """Generate log messages to stress-test the system.""" print(f"\n=== Stress Test: {num_messages} messages ===") start = time.perf_counter() for i in range(num_messages): logger.debug(f"Debug message {i}") if i % 100 == 0: logger.info(f"Progress: {i}/{num_messages}") if i % 250 == 0: logger.warning(f"Warning at {i}") if delay_ms > 0: time.sleep(delay_ms / 1000.0) elapsed = time.perf_counter() - start rate = num_messages / elapsed if elapsed > 0 else 0 print(f"Generated {num_messages} logs in {elapsed:.3f}s ({rate:.1f} msg/s)") return elapsed def test_batch_performance(): """Test che il batching funzioni correttamente.""" print("\n=== Test Batch Performance ===") root = tk.Tk() root.title("Logging Performance Test") root.geometry("800x600") # Create log widget log_widget = ScrolledText(root, state=tk.DISABLED, wrap=tk.WORD) log_widget.pack(fill=tk.BOTH, expand=True) # Setup logging system setup_basic_logging(root, LOGGING_CONFIG) add_tkinter_handler(log_widget, LOGGING_CONFIG) logger = get_logger("test_logger") logger.setLevel(logging.DEBUG) # Test 1: Rapid fire logging print("\nTest 1: 500 rapid messages (no delay)") elapsed1 = stress_test_logging(logger, num_messages=500, delay_ms=0) # Allow GUI to process print("Waiting for GUI to catch up...") for _ in range(30): # 3 seconds at 100ms poll interval root.update() time.sleep(0.1) # Test 2: Moderate rate logging print("\nTest 2: 200 messages with 10ms delay") elapsed2 = stress_test_logging(logger, num_messages=200, delay_ms=10) # Allow GUI to process print("Waiting for GUI to catch up...") for _ in range(30): root.update() time.sleep(0.1) # Test 3: Check widget line count (should be capped at max_lines) widget_lines = int(log_widget.index('end-1c').split('.')[0]) print(f"\nWidget line count: {widget_lines}") print(f"Expected max: 1000 (may be less if not enough messages)") print("\n=== Test Complete ===") print("Check the GUI window to verify:") print(" 1. All messages appeared (may be trimmed to last 1000)") print(" 2. Colors are correct (DEBUG=gray, INFO=black, WARNING=orange)") print(" 3. Window remained responsive during logging") print(" 4. Auto-scroll worked (if you were at bottom)") # Keep window open print("\nClose the window to exit...") root.mainloop() def test_adaptive_polling(): """Test che il polling adattivo funzioni.""" print("\n=== Test Adaptive Polling ===") root = tk.Tk() root.withdraw() # Hide window for this test setup_basic_logging(root, LOGGING_CONFIG) logger = get_logger("adaptive_test") logger.setLevel(logging.DEBUG) # Simulate activity burst followed by idle print("\nPhase 1: Activity burst (should poll fast)") for i in range(50): logger.debug(f"Active message {i}") root.update() time.sleep(0.05) # 50ms between messages print("\nPhase 2: Idle period (should slow down polling)") print("Monitoring for 15 seconds...") start = time.time() while (time.time() - start) < 15: root.update() time.sleep(0.1) print("\nPhase 3: Re-activate (should speed up again)") for i in range(20): logger.debug(f"Reactivated message {i}") root.update() time.sleep(0.05) print("\n=== Test Complete ===") print("Check console output for timing variations (not visible in this test)") print("In production, you can add debug logging to _process_global_log_queue()") root.destroy() def benchmark_comparison(): """Benchmark old vs new approach (simulated).""" print("\n=== Benchmark Comparison (Simulated) ===") # Simulate old approach: write each log individually print("\nOLD APPROACH (individual writes):") messages = [f"Message {i}" for i in range(1000)] start = time.perf_counter() simulated_widget_ops = 0 for msg in messages: # Simulate: configure(NORMAL) + insert + configure(DISABLED) + see(END) simulated_widget_ops += 4 elapsed_old = time.perf_counter() - start print(f" Simulated {simulated_widget_ops} widget operations") print(f" Estimated time (at 0.5ms/op): {simulated_widget_ops * 0.0005:.3f}s") # Simulate new approach: batch writes print("\nNEW APPROACH (batched writes):") BATCH_SIZE = 50 num_batches = len(messages) // BATCH_SIZE + (1 if len(messages) % BATCH_SIZE else 0) start = time.perf_counter() simulated_widget_ops = 0 for batch_idx in range(num_batches): # Simulate: configure(NORMAL) + N*insert + configure(DISABLED) + see(END) batch_size = min(BATCH_SIZE, len(messages) - batch_idx * BATCH_SIZE) simulated_widget_ops += (2 + batch_size + 1) # NORMAL + inserts + DISABLED + see elapsed_new = time.perf_counter() - start print(f" Simulated {simulated_widget_ops} widget operations") print(f" Estimated time (at 0.5ms/op): {simulated_widget_ops * 0.0005:.3f}s") improvement = ((4000 - simulated_widget_ops) / 4000) * 100 print(f"\n=== Improvement: {improvement:.1f}% fewer widget operations ===") if __name__ == "__main__": print("=== Logging Performance Test Suite ===") print("\nSelect test to run:") print(" 1. Batch Performance Test (interactive GUI)") print(" 2. Adaptive Polling Test") print(" 3. Benchmark Comparison (simulation)") print(" 4. Run all tests") choice = input("\nEnter choice (1-4): ").strip() if choice == "1": test_batch_performance() elif choice == "2": test_adaptive_polling() elif choice == "3": benchmark_comparison() elif choice == "4": test_adaptive_polling() time.sleep(2) benchmark_comparison() time.sleep(2) test_batch_performance() else: print("Invalid choice. Running benchmark only.") benchmark_comparison()