import time from unittest.mock import MagicMock, patch import pytest from semantica.pipeline.parallelism_manager import ParallelismManager, Task from semantica.pipeline.resource_scheduler import ResourceScheduler # ~~ Fixtures ~~ @pytest.fixture(autouse=True) def kill_hardware_checks(): with patch.object(ResourceScheduler, "_initialize_resources", return_value=None): yield @pytest.fixture(autouse=True) def kill_logging(): with patch("semantica.utils.logging.get_logger"): yield @pytest.fixture(autouse=True) def kill_tracker(): mock_tracker = MagicMock() mock_tracker.enabled = False with patch( "semantica.pipeline.parallelism_manager.get_progress_tracker", return_value=mock_tracker, ): yield def blocking_task(duration): """Simulates a task that waits for I/O (like a DB query or API call).""" time.sleep(duration) return True @pytest.fixture def thread_manager(): return ParallelismManager(max_workers=4, use_processes=False) @pytest.fixture def process_manager(): return ParallelismManager(max_workers=4, use_processes=True) # ~~ BENCHMARKS ~~ def test_parallel_vs_serial_io(benchmark, thread_manager): """ Runs 4 tasks that sleep for 0.1s. """ tasks = [ Task(task_id=f"t{i}", handler=blocking_task, args=(0.1,)) for i in range(4) ] def op(): return thread_manager.execute_parallel(tasks) benchmark.pedantic(op, iterations=1, rounds=5) def test_thread_pool_overhead(benchmark, thread_manager): """ Measures the raw cost of spinning up threads for zero-work tasks. """ # No-op handler noop = lambda: None tasks = [Task(task_id=f"t{i}", handler=noop) for i in range(100)] def op(): return thread_manager.execute_parallel(tasks) benchmark.pedantic(op, iterations=5, rounds=10) def test_process_pool_overhead(benchmark, process_manager): """ Measures overhead of ProcessPoolExecutor """ noop = lambda: None tasks = [Task(task_id=f"t{i}", handler=noop) for i in range(10)] def op(): return process_manager.execute_parallel(tasks) benchmark.pedantic(op, iterations=1, rounds=5)