6b7e6b44f1
Python Build and Type Check / python-ci (ubuntu-latest, 3.11) (push) Has been cancelled
Python Build and Type Check / python-ci (ubuntu-latest, 3.13) (push) Has been cancelled
Python Build and Type Check / python-ci (windows-latest, 3.11) (push) Has been cancelled
Python Build and Type Check / python-ci (windows-latest, 3.13) (push) Has been cancelled
Python Integration Tests / python-ci (ubuntu-latest, 3.13) (push) Has been cancelled
Python Integration Tests / python-ci (windows-latest, 3.13) (push) Has been cancelled
Python Notebook Tests / python-ci (ubuntu-latest, 3.13) (push) Has been cancelled
Python Notebook Tests / python-ci (windows-latest, 3.13) (push) Has been cancelled
Python Smoke Tests / python-ci (ubuntu-latest, 3.13) (push) Has been cancelled
Python Smoke Tests / python-ci (windows-latest, 3.13) (push) Has been cancelled
Python Unit Tests / python-ci (ubuntu-latest, 3.13) (push) Has been cancelled
Python Unit Tests / python-ci (windows-latest, 3.13) (push) Has been cancelled
gh-pages / build (push) Has been cancelled
Python Publish (pypi) / Upload release to PyPI (push) Has been cancelled
Spellcheck / spellcheck (push) Has been cancelled
96 lines
3.2 KiB
Python
96 lines
3.2 KiB
Python
# Copyright (C) 2025 Microsoft
|
|
# Licensed under the MIT License
|
|
|
|
"""Unit tests for WorkflowProfiler."""
|
|
|
|
import time
|
|
|
|
from graphrag.index.run.profiling import WorkflowProfiler
|
|
from graphrag.index.typing.stats import WorkflowMetrics
|
|
|
|
|
|
class TestWorkflowProfiler:
|
|
"""Tests for the WorkflowProfiler context manager."""
|
|
|
|
def test_captures_time(self):
|
|
"""Verify profiler captures elapsed time."""
|
|
with WorkflowProfiler() as profiler:
|
|
time.sleep(0.05) # Sleep 50ms
|
|
|
|
metrics = profiler.metrics
|
|
assert metrics.overall >= 0.05
|
|
assert metrics.overall < 0.5 # Should not take too long
|
|
|
|
def test_captures_peak_memory(self):
|
|
"""Verify profiler captures peak memory from allocations."""
|
|
with WorkflowProfiler() as profiler:
|
|
# Allocate ~1MB of data
|
|
data = [0] * (1024 * 1024 // 8) # 1M integers ≈ 8MB on 64-bit
|
|
_ = data # Keep reference to prevent GC
|
|
|
|
metrics = profiler.metrics
|
|
assert metrics.peak_memory_bytes > 0
|
|
|
|
def test_captures_memory_delta(self):
|
|
"""Verify profiler captures memory delta (current allocation)."""
|
|
with WorkflowProfiler() as profiler:
|
|
_data = [0] * 10000 # Keep allocation in scope
|
|
|
|
metrics = profiler.metrics
|
|
# Memory delta should be non-negative
|
|
assert metrics.memory_delta_bytes >= 0
|
|
|
|
def test_captures_tracemalloc_overhead(self):
|
|
"""Verify profiler captures tracemalloc's own memory overhead."""
|
|
with WorkflowProfiler() as profiler:
|
|
_ = list(range(1000))
|
|
|
|
metrics = profiler.metrics
|
|
assert metrics.tracemalloc_overhead_bytes > 0
|
|
|
|
def test_returns_workflow_metrics_dataclass(self):
|
|
"""Verify profiler.metrics returns a WorkflowMetrics instance."""
|
|
with WorkflowProfiler() as profiler:
|
|
pass
|
|
|
|
metrics = profiler.metrics
|
|
assert isinstance(metrics, WorkflowMetrics)
|
|
|
|
def test_all_metrics_populated(self):
|
|
"""Verify all four metrics are populated after profiling."""
|
|
with WorkflowProfiler() as profiler:
|
|
_ = list(range(100))
|
|
|
|
metrics = profiler.metrics
|
|
assert metrics.overall >= 0
|
|
assert metrics.peak_memory_bytes >= 0
|
|
assert metrics.memory_delta_bytes >= 0
|
|
assert metrics.tracemalloc_overhead_bytes >= 0
|
|
|
|
def test_handles_exception_in_context(self):
|
|
"""Verify profiler captures metrics even when exception is raised."""
|
|
profiler: WorkflowProfiler | None = None
|
|
try:
|
|
with WorkflowProfiler() as profiler:
|
|
_ = [0] * 1000
|
|
msg = "Test exception"
|
|
raise ValueError(msg)
|
|
except ValueError:
|
|
pass
|
|
|
|
assert profiler is not None
|
|
metrics = profiler.metrics
|
|
assert metrics.overall > 0
|
|
assert metrics.peak_memory_bytes > 0
|
|
|
|
def test_multiple_profilers_independent(self):
|
|
"""Verify multiple profiler instances don't interfere."""
|
|
with WorkflowProfiler() as profiler1:
|
|
time.sleep(0.02)
|
|
|
|
with WorkflowProfiler() as profiler2:
|
|
time.sleep(0.04)
|
|
|
|
# profiler2 should have longer time
|
|
assert profiler2.metrics.overall > profiler1.metrics.overall
|