Skip to content

Commit b87903f

Browse files
GeneAIclaude
authored andcommitted
perf: Optimize Cost Tracker with batch writes - 1,300x speedup
PERFORMANCE BREAKTHROUGH - Cost tracking: 32.02s → 0.025s for 1,000 requests (1,300x faster) - Function calls: 251M → 44K (5,700x reduction) - Disk writes: 1,000 → 20 (50x reduction) CHANGES - Batch writes (flush every 50 requests) - JSONL append-only format for new data - Real-time data (buffered requests included in summaries) - Zero data loss (atexit handler for crash safety) - Backward compatible with existing JSON format FILES MODIFIED - src/empathy_os/cost_tracker.py: Batch write optimization - tests/test_cost_tracker.py: Updated tests for buffered behavior - benchmarks/profile_suite.py: Fixed API compatibility - docs/PHASE2_PERFORMANCE_RESULTS.md: Comprehensive performance report TESTING - All 30 cost tracker tests passing - All 166 total tests passing - No regressions detected - Real-time data accuracy verified PROFILING RESULTS - Profiling suite operational - 4 profile files generated (.prof files for snakeviz) - Cost Tracker bottleneck identified and eliminated - Pattern Library, Scanner, Feedback Loops already optimal Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 68ead95 commit b87903f

File tree

10 files changed

+872
-74
lines changed

10 files changed

+872
-74
lines changed

benchmarks/profile_suite.py

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
import sys
1313
from pathlib import Path
1414

15-
# Add src to path
16-
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
15+
# Add project root to path (for scripts/ and src/)
16+
project_root = Path(__file__).parent.parent
17+
sys.path.insert(0, str(project_root))
18+
sys.path.insert(0, str(project_root / "src"))
1719

1820
from scripts.profile_utils import profile_function, time_function
1921

@@ -22,18 +24,19 @@
2224
@time_function
2325
def profile_scanner():
2426
"""Profile project scanner on real codebase."""
25-
from empathy_os.project_index import ProjectIndex
27+
from empathy_os.project_index.scanner import ProjectScanner
2628

2729
print("\n" + "=" * 60)
2830
print("Profiling: Project Scanner")
2931
print("=" * 60)
3032

31-
index = ProjectIndex(project_root=".")
32-
records, summary = index.scan()
33+
scanner = ProjectScanner(project_root=".")
34+
records, summary = scanner.scan()
3335

3436
print(f"✓ Scanned {summary.total_files} files")
37+
print(f"✓ Source files: {summary.source_files}")
38+
print(f"✓ Test files: {summary.test_files}")
3539
print(f"✓ Lines of code: {summary.total_lines_of_code:,}")
36-
print(f"✓ Test files: {summary.test_file_count}")
3740

3841

3942
@profile_function(output_file="benchmarks/profiles/pattern_library.prof")
@@ -51,20 +54,27 @@ def profile_pattern_library():
5154
# Create some test patterns
5255
for i in range(100):
5356
pattern = Pattern(
57+
id=f"pat_{i:03d}",
58+
agent_id=f"agent_{i % 10}",
59+
pattern_type=["sequential", "temporal", "conditional", "behavioral"][i % 4],
5460
name=f"test_pattern_{i}",
5561
description=f"Test pattern {i}",
56-
trigger=f"trigger_{i}",
57-
response=f"response_{i}",
5862
tags=[f"tag_{i % 10}"],
5963
confidence=0.5 + (i % 50) / 100,
6064
)
61-
library.add_pattern(pattern)
65+
library.contribute_pattern(f"agent_{i % 10}", pattern)
6266

6367
# Simulate pattern matching
6468
match_count = 0
6569
for i in range(1000):
66-
context = {"query": f"test query {i}", "history": [f"item {j}" for j in range(10)]}
67-
matches = library.match(context)
70+
context = {
71+
"task_type": f"task_{i % 5}",
72+
"user_role": "developer",
73+
"time_of_day": ["morning", "afternoon", "evening"][i % 3],
74+
}
75+
matches = library.query_patterns(
76+
agent_id=f"agent_{i % 10}", context=context, pattern_type=None
77+
)
6878
match_count += len(matches)
6979

7080
print(f"✓ Created 100 patterns")
@@ -94,11 +104,11 @@ def profile_cost_tracker():
94104
)
95105

96106
summary = tracker.get_summary(days=7)
97-
report = tracker.get_report(days=7)
98107

99108
print(f"✓ Logged 1000 requests")
100-
print(f"✓ Total cost: ${summary['total_cost']:.4f}")
101-
print(f"✓ Total tokens: {summary['total_tokens']:,}")
109+
print(f"✓ Actual cost: ${summary['actual_cost']:.4f}")
110+
print(f"✓ Input tokens: {summary['input_tokens']:,}")
111+
print(f"✓ Output tokens: {summary['output_tokens']:,}")
102112

103113

104114
@profile_function(output_file="benchmarks/profiles/feedback_loops.prof")
@@ -113,25 +123,37 @@ def profile_feedback_loops():
113123

114124
detector = FeedbackLoopDetector()
115125

116-
# Simulate session history
126+
# Generate test session history
127+
session_history = []
117128
for i in range(500):
118-
session_data = {
119-
"trust": 0.5 + (i % 50) / 100,
120-
"success_rate": 0.6 + (i % 40) / 100,
121-
"patterns_used": i % 10,
122-
"user_satisfaction": 0.7 + (i % 30) / 100,
123-
}
124-
detector.update_metrics(session_data)
125-
126-
# Detect loops
127-
virtuous = detector.detect_virtuous_cycle(metric="trust")
128-
vicious = detector.detect_vicious_cycle(metric="success_rate")
129-
active_loops = detector.detect_active_loop()
129+
session_history.append(
130+
{
131+
"trust": 0.5 + (i % 50) / 100,
132+
"success_rate": 0.6 + (i % 40) / 100,
133+
"patterns_used": i % 10,
134+
"user_satisfaction": 0.7 + (i % 30) / 100,
135+
}
136+
)
130137

131-
print(f"✓ Processed 500 session updates")
132-
print(f"✓ Virtuous cycles: {len([v for v in [virtuous] if v])}")
133-
print(f"✓ Vicious cycles: {len([v for v in [vicious] if v])}")
134-
print(f"✓ Active loops: {len(active_loops)}")
138+
# Detect loops multiple times (simulate repeated checks)
139+
virtuous_count = 0
140+
vicious_count = 0
141+
active_count = 0
142+
143+
for _ in range(100):
144+
if detector.detect_virtuous_cycle(session_history):
145+
virtuous_count += 1
146+
if detector.detect_vicious_cycle(session_history):
147+
vicious_count += 1
148+
active = detector.detect_active_loop(session_history)
149+
if active:
150+
active_count += 1
151+
152+
print(f"✓ Generated 500-item session history")
153+
print(f"✓ Ran 100 detection cycles")
154+
print(f"✓ Virtuous cycles detected: {virtuous_count}")
155+
print(f"✓ Vicious cycles detected: {vicious_count}")
156+
print(f"✓ Active loops detected: {active_count}")
135157

136158

137159
@time_function
40.2 KB
Binary file not shown.
3.43 KB
Binary file not shown.
2.42 KB
Binary file not shown.
344 KB
Binary file not shown.

0 commit comments

Comments
 (0)