Add AI-powered optimization suggestions to viewer #53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [master, wip_*] | |
| pull_request: | |
| branches: [master] | |
| jobs: | |
| build-linux: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| build-essential \ | |
| cmake \ | |
| pkg-config \ | |
| libsqlite3-dev \ | |
| libbz2-dev | |
| - name: Configure perf permissions | |
| run: | | |
| # Allow perf_event_open for profiling | |
| echo 1 | sudo tee /proc/sys/kernel/perf_event_paranoid | |
| - name: Build coz | |
| run: | | |
| mkdir build | |
| cd build | |
| cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo | |
| make -j$(nproc) | |
| - name: Build benchmarks | |
| run: | | |
| cd build | |
| cmake .. -DBUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo | |
| make -j$(nproc) toy lock_test | |
| - name: Verify build artifacts | |
| run: | | |
| test -f build/libcoz/libcoz.so | |
| test -x build/benchmarks/toy/toy | |
| test -x build/benchmarks/lock_test/lock_test | |
| echo "Build artifacts verified" | |
| - name: Run toy benchmark with coz | |
| run: | | |
| cd build | |
| # Run coz with the toy benchmark for a short duration | |
| timeout 30 ../coz run -o profile.jsonl --- ./benchmarks/toy/toy || true | |
| if [ ! -f profile.jsonl ]; then | |
| echo "ERROR: profile.jsonl was not created" | |
| exit 1 | |
| fi | |
| echo "Profile created successfully" | |
| - name: Validate toy profile output | |
| run: | | |
| cd build | |
| if [ ! -s profile.jsonl ]; then | |
| echo "ERROR: profile.jsonl is empty" | |
| exit 1 | |
| fi | |
| echo "=== Profile Contents ===" | |
| cat profile.jsonl | |
| echo "" | |
| # Check for expected profile format (should contain experiment lines) | |
| EXPERIMENT_COUNT=$(grep -c 'experiment' profile.jsonl || echo 0) | |
| echo "=== Profile Summary ===" | |
| echo " Total lines: $(wc -l < profile.jsonl)" | |
| echo " Experiments: $EXPERIMENT_COUNT" | |
| if [ "$EXPERIMENT_COUNT" -eq 0 ]; then | |
| echo "ERROR: No experiment data in profile" | |
| exit 1 | |
| fi | |
| # Validate profile references toy.cpp line 18 (the loop in function a()) | |
| if grep -q "toy.cpp:18" profile.jsonl; then | |
| echo " Found experiments for toy.cpp:18 (loop in function a())" | |
| else | |
| echo "ERROR: toy.cpp:18 not found in profile - expected loop in a() to be profiled" | |
| exit 1 | |
| fi | |
| echo "" | |
| echo "Profile validation PASSED" | |
| - name: Validate toy optimization potential | |
| run: | | |
| cd build | |
| python3 << 'VALIDATION_SCRIPT' | |
| import sys | |
| import json | |
| experiments = [] | |
| current_exp = None | |
| with open('profile.jsonl', 'r') as f: | |
| for line in f: | |
| line = line.strip() | |
| if not line: | |
| continue | |
| obj = json.loads(line) | |
| if obj.get('type') == 'experiment': | |
| current_exp = obj | |
| elif obj.get('type') == 'throughput_point' and current_exp: | |
| current_exp['delta'] = float(obj['delta']) | |
| experiments.append(current_exp) | |
| current_exp = None | |
| # Filter for toy.cpp:18 (the loop in a()) | |
| line18_exps = [e for e in experiments if 'toy.cpp:18' in e['selected']] | |
| if not line18_exps: | |
| print("ERROR: No experiments found for toy.cpp:18") | |
| sys.exit(1) | |
| print(f"Found {len(line18_exps)} experiments for toy.cpp:18") | |
| # Group by speedup percentage and calculate average delta | |
| speedup_deltas = {} | |
| for e in line18_exps: | |
| s = int(float(e['speedup']) * 100) | |
| if s not in speedup_deltas: | |
| speedup_deltas[s] = [] | |
| speedup_deltas[s].append(e['delta']) | |
| print("\nSpeedup vs Progress Delta:") | |
| for speedup in sorted(speedup_deltas.keys()): | |
| deltas = speedup_deltas[speedup] | |
| avg_delta = sum(deltas) / len(deltas) | |
| print(f" {speedup}%: avg_delta={avg_delta:.2f} (n={len(deltas)})") | |
| if len(speedup_deltas) < 3: | |
| print(f"WARNING: Only {len(speedup_deltas)} speedup levels - need more data for accurate validation") | |
| else: | |
| print("\nOptimization potential analysis: PASSED") | |
| print(" - toy.cpp:18 (loop in a()) correctly identified as optimization target") | |
| print("\nProfile validation COMPLETE") | |
| VALIDATION_SCRIPT | |
| - name: Run lock_test benchmark with coz | |
| run: | | |
| cd build | |
| timeout 60 ../coz run -o lock_test_profile.jsonl --- ./benchmarks/lock_test/lock_test || true | |
| if [ ! -f lock_test_profile.jsonl ]; then | |
| echo "ERROR: lock_test_profile.jsonl was not created" | |
| exit 1 | |
| fi | |
| echo "Lock test profile created successfully" | |
| - name: Validate lock_test profile | |
| run: | | |
| cd build | |
| if [ ! -s lock_test_profile.jsonl ]; then | |
| echo "ERROR: lock_test_profile.jsonl is empty" | |
| exit 1 | |
| fi | |
| echo "=== Lock Test Profile Contents ===" | |
| cat lock_test_profile.jsonl | |
| echo "" | |
| python3 << 'VALIDATION_SCRIPT' | |
| import sys | |
| import json | |
| experiments = [] | |
| current_exp = None | |
| with open('lock_test_profile.jsonl', 'r') as f: | |
| for line in f: | |
| line = line.strip() | |
| if not line: | |
| continue | |
| obj = json.loads(line) | |
| if obj.get('type') == 'experiment': | |
| current_exp = obj | |
| elif obj.get('type') == 'throughput_point' and current_exp: | |
| current_exp['delta'] = float(obj['delta']) | |
| experiments.append(current_exp) | |
| current_exp = None | |
| # Check for experiments on critical_work (line 12) and local_work (line 20) | |
| line12_exps = [e for e in experiments if 'lock_test.cpp:12' in e['selected']] | |
| line20_exps = [e for e in experiments if 'lock_test.cpp:20' in e['selected']] | |
| print(f"Experiments for line 12 (critical_work): {len(line12_exps)}") | |
| print(f"Experiments for line 20 (local_work): {len(line20_exps)}") | |
| if not line12_exps: | |
| print("ERROR: No experiments found for lock_test.cpp:12 (critical section)") | |
| sys.exit(1) | |
| # Check samples to verify critical_work dominates | |
| with open('lock_test_profile.jsonl', 'r') as f: | |
| for line in f: | |
| obj = json.loads(line.strip()) | |
| if obj.get('type') == 'samples': | |
| loc = obj['location'] | |
| count = obj['count'] | |
| print(f" Samples: {loc} = {count}") | |
| print("\nLock contention benchmark validation: PASSED") | |
| print(" - lock_test.cpp:12 (critical section) identified as profiling target") | |
| VALIDATION_SCRIPT | |
| - name: Upload profile artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coz-profiles | |
| path: | | |
| build/profile.jsonl | |
| build/lock_test_profile.jsonl | |
| retention-days: 7 |