@@ -181,161 +181,11 @@ jobs:
181181
182182 - name : Compute scaling efficiency metrics
183183 run : |
184- python3 << 'EOF'
185- import json
186-
187- with open('output-saturation.json') as f:
188- data = json.load(f)
189-
190- # Group by cores and protocol - collect throughput and CPU
191- throughput = {}
192- cpu_norm = {}
193- for entry in data:
194- extra = entry['extra']
195- parts = extra.split(' - ')
196- if len(parts) < 3:
197- continue
198-
199- cores = parts[2].split('/')[0].split()[0]
200- protocol = extra.split('/')[1].split(' - ')[0] if '/' in extra else 'unknown'
201- key = f"{cores}core-{protocol}"
202-
203- if entry['name'] == 'logs_received_rate':
204- throughput[key] = entry['value']
205- elif entry['name'] == 'cpu_percentage_normalized_avg':
206- cpu_norm[key] = entry['value']
207-
208- # Calculate scaling metrics
209- scaling_metrics = []
210- for protocol in ['OTLP-ATTR-OTLP', 'OTAP-ATTR-OTLP']:
211- baseline = throughput.get(f"1core-{protocol}", 1)
212-
213- for cores in ['1', '2', '4', '8']:
214- key = f"{cores}core-{protocol}"
215- if key in throughput:
216- cores_int = int(cores)
217- actual_speedup = throughput[key] / baseline if baseline > 0 else 0
218- ideal_speedup = cores_int
219- efficiency = (actual_speedup / ideal_speedup) * 100 if ideal_speedup > 0 else 0
220- per_core = throughput[key] / cores_int
221-
222- # Add efficiency metric (higher is better)
223- scaling_metrics.append({
224- "name": "scaling_efficiency",
225- "unit": "%",
226- "value": efficiency,
227- "extra": f"Continuous - Saturation - {cores} Core(s)/{protocol} - Scaling Efficiency"
228- })
229-
230- # Add per-core throughput (should remain constant for linear scaling)
231- scaling_metrics.append({
232- "name": "per_core_throughput",
233- "unit": "logs/sec/core",
234- "value": per_core,
235- "extra": f"Continuous - Saturation - {cores} Core(s)/{protocol} - Per-Core Throughput"
236- })
237-
238- # Add speedup metric
239- scaling_metrics.append({
240- "name": "speedup",
241- "unit": "x",
242- "value": actual_speedup,
243- "extra": f"Continuous - Saturation - {cores} Core(s)/{protocol} - Speedup vs 1-core"
244- })
245-
246- # Merge with original data
247- data.extend(scaling_metrics)
248-
249- with open('output-saturation.json', 'w') as f:
250- json.dump(data, f, indent=2)
251-
252- print(f"Added {len(scaling_metrics)} scaling metrics")
253- EOF
184+ python3 .github/workflows/scripts/compute-scaling-metrics.py output-saturation.json output-saturation.json
254185
255186 - name : Generate scaling analysis summary
256187 run : |
257- python3 << 'EOF'
258- import json
259- import os
260-
261- with open('output-saturation.json') as f:
262- data = json.load(f)
263-
264- # Group metrics by configuration
265- metrics = {}
266- for entry in data:
267- extra = entry['extra']
268- parts = extra.split(' - ')
269- if len(parts) < 3:
270- continue
271-
272- cores = parts[2].split('/')[0].split()[0]
273- protocol = extra.split('/')[1].split(' - ')[0] if '/' in extra else 'unknown'
274- key = f"{cores}core-{protocol}"
275-
276- if key not in metrics:
277- metrics[key] = {}
278-
279- name = entry['name']
280- if name == 'logs_received_rate':
281- metrics[key]['throughput'] = entry['value']
282- elif name == 'cpu_percentage_normalized_avg':
283- metrics[key]['cpu'] = entry['value']
284- elif name == 'speedup':
285- metrics[key]['speedup'] = entry['value']
286- elif name == 'scaling_efficiency':
287- metrics[key]['efficiency'] = entry['value']
288- elif name == 'dropped_logs_percentage':
289- metrics[key]['dropped'] = entry['value']
290-
291- # Write to GitHub Step Summary
292- with open(os.environ['GITHUB_STEP_SUMMARY'], 'a') as f:
293- f.write("\n## 🚀 Core Scaling Analysis\n\n")
294- f.write("### OTLP Protocol\n\n")
295- f.write("| Cores | Throughput (logs/s) | Speedup | Efficiency | CPU % | Dropped % |\n")
296- f.write("|-------|--------------------:|--------:|-----------:|------:|----------:|\n")
297-
298- for cores in ['1', '2', '4', '8']:
299- key = f"{cores}core-OTLP-ATTR-OTLP"
300- if key in metrics and 'throughput' in metrics[key]:
301- m = metrics[key]
302- speedup = m.get('speedup', 0)
303- efficiency = m.get('efficiency', 0)
304- cpu = m.get('cpu', 0)
305- throughput = m.get('throughput', 0)
306- dropped = m.get('dropped', 0)
307-
308- # Add status emoji
309- eff_emoji = "🟢" if efficiency >= 80 else "🟡" if efficiency >= 60 else "🔴"
310- cpu_emoji = "✅" if cpu >= 90 else "⚠️" if cpu >= 70 else "❌"
311-
312- f.write(f"| {cores} {eff_emoji} | {throughput:>15,.0f} | {speedup:>5.2f}x | {efficiency:>8.1f}% | {cpu:>4.1f}% {cpu_emoji} | {dropped:>6.2f}% |\n")
313-
314- f.write("\n### OTAP Protocol\n\n")
315- f.write("| Cores | Throughput (logs/s) | Speedup | Efficiency | CPU % | Dropped % |\n")
316- f.write("|-------|--------------------:|--------:|-----------:|------:|----------:|\n")
317-
318- for cores in ['1', '2', '4', '8']:
319- key = f"{cores}core-OTAP-ATTR-OTLP"
320- if key in metrics and 'throughput' in metrics[key]:
321- m = metrics[key]
322- speedup = m.get('speedup', 0)
323- efficiency = m.get('efficiency', 0)
324- cpu = m.get('cpu', 0)
325- throughput = m.get('throughput', 0)
326- dropped = m.get('dropped', 0)
327-
328- # Add status emoji
329- eff_emoji = "🟢" if efficiency >= 80 else "🟡" if efficiency >= 60 else "🔴"
330- cpu_emoji = "✅" if cpu >= 90 else "⚠️" if cpu >= 70 else "❌"
331-
332- f.write(f"| {cores} {eff_emoji} | {throughput:>15,.0f} | {speedup:>5.2f}x | {efficiency:>8.1f}% | {cpu:>4.1f}% {cpu_emoji} | {dropped:>6.2f}% |\n")
333-
334- f.write("\n**Legend:**\n")
335- f.write("- 🟢 Efficiency ≥80% | 🟡 60-80% | 🔴 <60%\n")
336- f.write("- ✅ CPU ≥90% (saturated) | ⚠️ 70-90% | ❌ <70% (under-utilized)\n")
337- f.write("- **Ideal Linear Scaling:** Efficiency = 100%, Speedup = # of cores\n\n")
338- EOF
188+ python3 .github/workflows/scripts/generate-scaling-summary.py output-saturation.json
339189
340190 - name : Update pipeline benchmark data and deploy to GitHub Pages
341191 uses : benchmark-action/github-action-benchmark@d48d326b4ca9ba73ca0cd0d59f108f9e02a381c7
0 commit comments