feat(perf): Add performance tests and high-precision timing
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import pytest
|
||||
from src.models import Ticket
|
||||
from src.dag_engine import TrackDAG
|
||||
from src.performance_monitor import get_monitor
|
||||
|
||||
def test_dag_performance():
|
||||
perf = get_monitor()
|
||||
perf.enabled = True
|
||||
|
||||
num_tickets = 500
|
||||
tickets = []
|
||||
# Create a complex DAG: linear dependencies + branching
|
||||
for i in range(num_tickets):
|
||||
deps = []
|
||||
if i > 0:
|
||||
# Linear dependency
|
||||
deps.append(f"ticket_{i-1}")
|
||||
if i > 10:
|
||||
# Branching dependency (binary tree-ish)
|
||||
deps.append(f"ticket_{i//2}")
|
||||
if i > 50:
|
||||
# More cross-links
|
||||
deps.append(f"ticket_{i-10}")
|
||||
|
||||
tickets.append(Ticket(
|
||||
id=f"ticket_{i}",
|
||||
description=f"Ticket number {i}",
|
||||
depends_on=deps,
|
||||
status="todo"
|
||||
))
|
||||
|
||||
dag = TrackDAG(tickets[::-1])
|
||||
|
||||
# 1. Measure has_cycle()
|
||||
cycle_found = dag.has_cycle()
|
||||
assert cycle_found is False
|
||||
|
||||
# 2. Measure topological_sort()
|
||||
sorted_ids = dag.topological_sort()
|
||||
assert len(sorted_ids) == num_tickets
|
||||
|
||||
# 3. Measure cascade_blocks()
|
||||
tickets[0].status = "blocked"
|
||||
dag.cascade_blocks()
|
||||
|
||||
# Verify all are blocked
|
||||
for t in tickets:
|
||||
assert t.status == "blocked", f"Ticket {t.id} failed to cascade block"
|
||||
|
||||
# 4. Verify metrics were recorded
|
||||
metrics = perf.get_metrics()
|
||||
assert "time_dag_has_cycle_ms" in metrics
|
||||
assert "time_dag_topological_sort_ms" in metrics
|
||||
assert "time_dag_cascade_blocks_ms" in metrics
|
||||
|
||||
# Output results for visibility when running with -s
|
||||
print(f"\n[PERF] DAG Performance (n={num_tickets}):")
|
||||
print(f" has_cycle: {metrics['time_dag_has_cycle_ms']:.4f} ms")
|
||||
print(f" topological_sort: {metrics['time_dag_topological_sort_ms']:.4f} ms")
|
||||
print(f" cascade_blocks: {metrics['time_dag_cascade_blocks_ms']:.4f} ms")
|
||||
|
||||
def test_dag_edge_cases():
|
||||
# Test cycle detection correctness
|
||||
t1 = Ticket(id="a", description="a", depends_on=["b"])
|
||||
t2 = Ticket(id="b", description="b", depends_on=["c"])
|
||||
t3 = Ticket(id="c", description="c", depends_on=["a"])
|
||||
dag = TrackDAG([t1, t2, t3])
|
||||
assert dag.has_cycle() is True
|
||||
with pytest.raises(ValueError, match="Dependency cycle detected"):
|
||||
dag.topological_sort()
|
||||
|
||||
# Test empty DAG
|
||||
dag_empty = TrackDAG([])
|
||||
assert dag_empty.has_cycle() is False
|
||||
assert dag_empty.topological_sort() == []
|
||||
Reference in New Issue
Block a user