Implemetned better buffering and high frequency tracing
This commit is contained in:
@@ -80,6 +80,7 @@ enum InternalEvent {
|
||||
TraceRequested(String),
|
||||
ClearTrace(String),
|
||||
UdpStats(u64),
|
||||
UdpDropped(u32),
|
||||
}
|
||||
|
||||
// --- App State ---
|
||||
@@ -126,6 +127,7 @@ struct MarteDebugApp {
|
||||
node_info: String,
|
||||
|
||||
udp_packets: u64,
|
||||
udp_dropped: u64,
|
||||
|
||||
forcing_dialog: Option<ForcingDialog>,
|
||||
|
||||
@@ -198,6 +200,7 @@ impl MarteDebugApp {
|
||||
selected_node: "".to_string(),
|
||||
node_info: "".to_string(),
|
||||
udp_packets: 0,
|
||||
udp_dropped: 0,
|
||||
forcing_dialog: None,
|
||||
tx_cmd,
|
||||
rx_events,
|
||||
@@ -206,7 +209,6 @@ impl MarteDebugApp {
|
||||
}
|
||||
|
||||
fn render_tree(&mut self, ui: &mut egui::Ui, item: &TreeItem, path: String) {
|
||||
// Strip "Root" from paths to match server discovery
|
||||
let current_path = if path.is_empty() {
|
||||
if item.name == "Root" { "".to_string() } else { item.name.clone() }
|
||||
} else {
|
||||
@@ -387,6 +389,7 @@ fn tcp_log_worker(shared_config: Arc<Mutex<ConnectionConfig>>, tx_events: Sender
|
||||
fn udp_worker(shared_config: Arc<Mutex<ConnectionConfig>>, id_to_meta: Arc<Mutex<HashMap<u32, SignalMetadata>>>, traced_data: Arc<Mutex<HashMap<String, TraceData>>>, tx_events: Sender<InternalEvent>) {
|
||||
let mut current_version = 0;
|
||||
let mut socket: Option<UdpSocket> = None;
|
||||
let mut last_seq: Option<u32> = None;
|
||||
|
||||
loop {
|
||||
let (ver, port) = {
|
||||
@@ -403,6 +406,9 @@ fn udp_worker(shared_config: Arc<Mutex<ConnectionConfig>>, id_to_meta: Arc<Mutex
|
||||
let _ = sock.set_reuse_address(true);
|
||||
#[cfg(all(unix, not(target_os = "solaris"), not(target_os = "illumos")))]
|
||||
let _ = sock.set_reuse_port(true);
|
||||
|
||||
// CRITICAL: Increase receive buffer to 10MB to avoid drops at 100kHz
|
||||
let _ = sock.set_recv_buffer_size(10 * 1024 * 1024);
|
||||
|
||||
let addr = format!("0.0.0.0:{}", port_num).parse::<std::net::SocketAddr>().unwrap();
|
||||
if sock.bind(&addr.into()).is_ok() {
|
||||
@@ -417,6 +423,7 @@ fn udp_worker(shared_config: Arc<Mutex<ConnectionConfig>>, id_to_meta: Arc<Mutex
|
||||
continue;
|
||||
}
|
||||
let _ = socket.as_ref().unwrap().set_read_timeout(Some(std::time::Duration::from_millis(500)));
|
||||
last_seq = None;
|
||||
}
|
||||
|
||||
let s = socket.as_ref().unwrap();
|
||||
@@ -431,7 +438,7 @@ fn udp_worker(shared_config: Arc<Mutex<ConnectionConfig>>, id_to_meta: Arc<Mutex
|
||||
|
||||
if let Ok(n) = s.recv(&mut buf) {
|
||||
total_packets += 1;
|
||||
if (total_packets % 100) == 0 {
|
||||
if (total_packets % 500) == 0 {
|
||||
let _ = tx_events.send(InternalEvent::UdpStats(total_packets));
|
||||
}
|
||||
|
||||
@@ -440,14 +447,27 @@ fn udp_worker(shared_config: Arc<Mutex<ConnectionConfig>>, id_to_meta: Arc<Mutex
|
||||
let mut magic_buf = [0u8; 4]; magic_buf.copy_from_slice(&buf[0..4]);
|
||||
if u32::from_le_bytes(magic_buf) != 0xDA7A57AD { continue; }
|
||||
|
||||
// Sequence check
|
||||
let mut seq_buf = [0u8; 4]; seq_buf.copy_from_slice(&buf[4..8]);
|
||||
let seq = u32::from_le_bytes(seq_buf);
|
||||
if let Some(last) = last_seq {
|
||||
if seq != last + 1 {
|
||||
let dropped = if seq > last { seq - last - 1 } else { 0 };
|
||||
if dropped > 0 {
|
||||
let _ = tx_events.send(InternalEvent::UdpDropped(dropped));
|
||||
}
|
||||
}
|
||||
}
|
||||
last_seq = Some(seq);
|
||||
|
||||
let mut count_buf = [0u8; 4]; count_buf.copy_from_slice(&buf[16..20]);
|
||||
let count = u32::from_le_bytes(count_buf);
|
||||
|
||||
let now = start_time.elapsed().as_secs_f64();
|
||||
let mut offset = 20;
|
||||
|
||||
let mut local_updates: HashMap<String, Vec<[f64; 2]>> = HashMap::new();
|
||||
let metas = id_to_meta.lock().unwrap();
|
||||
let mut data_map = traced_data.lock().unwrap();
|
||||
|
||||
for _ in 0..count {
|
||||
if offset + 8 > n { break; }
|
||||
@@ -484,14 +504,26 @@ fn udp_worker(shared_config: Arc<Mutex<ConnectionConfig>>, id_to_meta: Arc<Mutex
|
||||
};
|
||||
|
||||
for name in &meta.names {
|
||||
if let Some(entry) = data_map.get_mut(name) {
|
||||
entry.values.push_back([now, val]);
|
||||
if entry.values.len() > 5000 { entry.values.pop_front(); }
|
||||
}
|
||||
local_updates.entry(name.clone()).or_default().push([now, val]);
|
||||
}
|
||||
}
|
||||
offset += size as usize;
|
||||
}
|
||||
drop(metas);
|
||||
|
||||
if !local_updates.is_empty() {
|
||||
let mut data_map = traced_data.lock().unwrap();
|
||||
for (name, new_points) in local_updates {
|
||||
if let Some(entry) = data_map.get_mut(&name) {
|
||||
for point in new_points {
|
||||
entry.values.push_back(point);
|
||||
}
|
||||
while entry.values.len() > 10000 {
|
||||
entry.values.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -531,7 +563,7 @@ impl eframe::App for MarteDebugApp {
|
||||
}
|
||||
InternalEvent::TraceRequested(name) => {
|
||||
let mut data_map = self.traced_signals.lock().unwrap();
|
||||
data_map.entry(name).or_insert_with(|| TraceData { values: VecDeque::with_capacity(5000) });
|
||||
data_map.entry(name).or_insert_with(|| TraceData { values: VecDeque::with_capacity(10000) });
|
||||
}
|
||||
InternalEvent::ClearTrace(name) => {
|
||||
let mut data_map = self.traced_signals.lock().unwrap();
|
||||
@@ -547,6 +579,9 @@ impl eframe::App for MarteDebugApp {
|
||||
InternalEvent::UdpStats(count) => {
|
||||
self.udp_packets = count;
|
||||
}
|
||||
InternalEvent::UdpDropped(dropped) => {
|
||||
self.udp_dropped += dropped as u64;
|
||||
}
|
||||
InternalEvent::Connected => {
|
||||
self.connected = true;
|
||||
let _ = self.tx_cmd.send("TREE".to_string());
|
||||
@@ -636,7 +671,7 @@ impl eframe::App for MarteDebugApp {
|
||||
}
|
||||
}
|
||||
ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
|
||||
ui.label(format!("UDP Packets: {}", self.udp_packets));
|
||||
ui.label(format!("UDP: OK [{}] / DROPPED [{}]", self.udp_packets, self.udp_dropped));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -797,7 +832,6 @@ impl eframe::App for MarteDebugApp {
|
||||
ui.horizontal(|ui| {
|
||||
ui.heading("Oscilloscope");
|
||||
if ui.button("🔄 Reset View").clicked() {
|
||||
// This will force auto-bounds to re-calculate on next frame
|
||||
}
|
||||
});
|
||||
let plot = Plot::new("traces_plot")
|
||||
|
||||
Reference in New Issue
Block a user