fixes for better stats

This commit is contained in:
Bob 2025-12-15 08:18:24 -08:00
parent b86bb81110
commit d290589888
3 changed files with 45 additions and 27 deletions

View File

@ -27,7 +27,7 @@ static EventGroupHandle_t s_iperf_event_group = NULL;
#define IPERF_IP_READY_BIT (1 << 0)
#define IPERF_STOP_REQ_BIT (1 << 1)
#define RATE_CHECK_INTERVAL_US 500000
#define MIN_RATE_CHECK_INTERVAL_US 250000
#define MIN_PACING_INTERVAL_US 100
typedef struct {
@ -105,32 +105,36 @@ void iperf_print_status(void) {
}
// 3. Compute Session Bandwidth
// Logic: If running, use current time. If stopped, use stored end time.
float avg_bw_mbps = 0.0f;
if (s_session_start_time > 0) {
int64_t end_t = (s_stats.running) ? esp_timer_get_time() : s_session_end_time;
if (end_t > s_session_start_time) {
double duration_sec = (double)(end_t - s_session_start_time) / 1000000.0;
// Only calc if duration is significant to avoid divide-by-tiny-number
if (duration_sec > 0.001) {
// Total bits = packets * packet_size * 8
double total_bits = (double)s_session_packets * (double)s_iperf_ctrl.cfg.send_len * 8.0;
avg_bw_mbps = (float)(total_bits / duration_sec / 1000000.0);
}
}
}
// New Format: Standard Stats
// 4. Calculate State Percentages
double total_us = (double)(s_time_tx_us + s_time_slow_us + s_time_stalled_us);
if (total_us < 1.0) total_us = 1.0; // Prevent div/0
double pct_tx = ((double)s_time_tx_us / total_us) * 100.0;
double pct_slow = ((double)s_time_slow_us / total_us) * 100.0;
double pct_stalled = ((double)s_time_stalled_us / total_us) * 100.0;
// Standard Stats
printf("IPERF_STATUS: Src=%s, Dst=%s, Running=%d, Config=%" PRIu32 ", Actual=%" PRIu32 ", Err=%.1f%%, Pkts=%" PRIu64 ", AvgBW=%.2f Mbps\n",
src_ip, dst_ip, s_stats.running, s_stats.config_pps, s_stats.actual_pps, err, s_session_packets, avg_bw_mbps);
// New Format: State Durations & Edges
printf("IPERF_STATES: TX=%.2fs (%lu), SLOW=%.2fs (%lu), STALLED=%.2fs (%lu)\n",
(double)s_time_tx_us/1000000.0, (unsigned long)s_edge_tx,
(double)s_time_slow_us/1000000.0, (unsigned long)s_edge_slow,
(double)s_time_stalled_us/1000000.0, (unsigned long)s_edge_stalled);
// New Format: Time + Percentage + Edges
// Example: TX=15.15s/28.5% (15)
printf("IPERF_STATES: TX=%.2fs/%.1f%% (%lu), SLOW=%.2fs/%.1f%% (%lu), STALLED=%.2fs/%.1f%% (%lu)\n",
(double)s_time_tx_us/1000000.0, pct_tx, (unsigned long)s_edge_tx,
(double)s_time_slow_us/1000000.0, pct_slow, (unsigned long)s_edge_slow,
(double)s_time_stalled_us/1000000.0, pct_stalled, (unsigned long)s_edge_stalled);
}
// --- Network Events ---

View File

@ -59,23 +59,26 @@ class SerialController(asyncio.Protocol):
}
elif "IPERF_STATES" in line:
m = re.search(r'TX=([\d\.]+)s \((\d+)\), SLOW=([\d\.]+)s \((\d+)\), STALLED=([\d\.]+)s \((\d+)\)', line)
# NEW REGEX: Matches "TX=15.15s/28.5% (15)"
# Groups: 1=Time, 2=Pct, 3=Count (Repeated for SLOW and STALLED)
m = re.search(r'TX=([\d\.]+)s/([\d\.]+)% \((\d+)\), SLOW=([\d\.]+)s/([\d\.]+)% \((\d+)\), STALLED=([\d\.]+)s/([\d\.]+)% \((\d+)\)', line)
if m:
self.status_data['states'] = {
'tx_t': m.group(1), 'tx_c': m.group(2),
'sl_t': m.group(3), 'sl_c': m.group(4),
'st_t': m.group(5), 'st_c': m.group(6)
'tx_t': m.group(1), 'tx_p': m.group(2), 'tx_c': m.group(3),
'sl_t': m.group(4), 'sl_p': m.group(5), 'sl_c': m.group(6),
'st_t': m.group(7), 'st_p': m.group(8), 'st_c': m.group(9)
}
if 'main' in self.status_data and 'states' in self.status_data:
if not self.completion_future.done():
d = self.status_data['main']
s = self.status_data['states']
# Updated Output Format
output = (f"{d['src']} -> {d['dst']} | {d['run']}, "
f"Cfg:{d['cfg']}, Act:{d['act']}, Err:{d['err']}%, Pkts:{d['pkts']}, BW:{d['bw']}M | "
f"TX:{s['tx_t']}s({s['tx_c']}) "
f"SL:{s['sl_t']}s({s['sl_c']}) "
f"ST:{s['st_t']}s({s['st_c']})")
f"TX:{s['tx_t']}s/{s['tx_p']}%({s['tx_c']}) "
f"SL:{s['sl_t']}s/{s['sl_p']}%({s['sl_c']}) "
f"ST:{s['st_t']}s/{s['st_p']}%({s['st_c']})")
self.completion_future.set_result(output)
self.transport.close()
return

View File

@ -588,19 +588,30 @@ async def run_deployment(args):
max_c = args.max_concurrent if args.max_concurrent else (1 if args.devices and not args.config_only else DEFAULT_MAX_CONCURRENT_FLASH)
flash_sem = asyncio.Semaphore(max_c)
tasks = []
for i, dev in enumerate(devs):
# --- ROBUST IP CALCULATION LOGIC ---
if args.ip_device_based:
# Mode A: Offset based on physical port number (e.g. 14 for ttyUSB14)
offset = extract_device_number(dev.device)
print(f" [{dev.device}] Using device-based IP offset: +{offset}")
else:
# Mode B: Sequential offset based on loop index
offset = i
print(f" [{dev.device}] Using sequential IP offset: +{offset}")
# Mode A: Offset based on physical port number (e.g. 14 for esp_port_14)
raw_port_number = extract_device_number(dev.device)
# FIX: Subtract 1 from the raw port number to make the offset zero-based.
# This ensures esp_port_1 gets the exact --start-ip (offset 0).
offset = raw_port_number - 1
target_ip = str(start_ip + offset)
# Display the result using the clear 'DEVICE IP' label
print(f" [{dev.device}] Using device-based IP offset: +{offset} (Raw Port: {raw_port_number}). DEVICE IP: {target_ip}")
else:
# Mode B: Sequential offset based on loop index (zero-based)
offset = i
target_ip = str(start_ip + offset)
# Display the result using the clear 'DEVICE IP' label
print(f" [{dev.device}] Using sequential IP offset: +{offset}. DEVICE IP: {target_ip}")
target_ip = str(start_ip + offset)
tasks.append(UnifiedDeployWorker(dev.device, target_ip, args, project_dir, flash_sem).run())
results = await asyncio.gather(*tasks)