Coverage for perf.py: 65%

1"""Performance timing utilities for Vibelexity."""

2

3 from __future__ import annotations

4

5 import time

6 from contextlib import contextmanager

7

8

9@contextmanager

10 def time_block():

11 """Context manager to measure execution time in milliseconds."""

12 start = time.perf_counter()

13 elapsed = [0.0]

14 yield elapsed

15 elapsed[0] = (time.perf_counter() - start) * 1000

16

17

18 TimingManager = dict[str, list[float]]

19"""Type alias for timing manager: maps metric names to list of timings."""

20

21

22 def create_timing_manager() -> TimingManager:

23 """Create a new timing manager for collecting metric timings."""

24 return {

25 "parse": [],

26 "collect_functions": [],

27 "cognitive": [],

28 "halstead": [],

29 "npath": [],

30 "dtd": [],

31 "cyclomatic": [],

32 "lloc": [],

33 "mi": [],

34 "ldi": [],

35 "duplication": [],

36 }

37

38

39 def compute_stats(timings: list[float]) -> dict[str, float]:

40 """Compute average and total for a list of timings."""

41 if not timings:

42 return {"average_ms": 0.0, "total_ms": 0.0, "count": 0}

43 return {

44 "average_ms": round(sum(timings) / len(timings), 2),

45 "total_ms": round(sum(timings), 2),

46 "count": len(timings),

47 }

48

49

50 def get_timing_summary(timing_manager: TimingManager) -> dict[str, dict[str, float]]:

51 """Get summary statistics for all metrics."""

52 metrics = [

53 "parse",

54 "collect_functions",

55 "cognitive",

56 "halstead",

57 "npath",

58 "dtd",

59 "cyclomatic",

60 "lloc",

61 "mi",

62 "ldi",

63 "duplication",

64 ]

65 result = {}

66 for metric in metrics:

67 result[metric] = compute_stats(timing_manager.get(metric, []))

68 return result