基于时间条件的两线程之间的数据发送与接收
继续讨论这个 话题
如何才能实现最高性能? 是否有可能在代码中避免克隆?以及如何正确计数纳秒? 我没能让纳秒的输出始终显示为九位数并带前导零以便清晰。 两个线程都需要在执行此任务之外还能做其他工作,但不能以牺牲数据传输和接收速度为代价。 如何组织代码才能实现这一点?

mod.rs : pub mod txrx;
main.rs
use std::sync::mpsc;
use std::time::{SystemTime, UNIX_EPOCH};
mod tst01;
use tst01::txrx::{DataSR};
fn main() {
let (tx_01, rx_01) = mpsc::channel();
let tx_01_clone: std::sync::mpsc::Sender<(SystemTime, Vec<String>)> = tx_01.clone();
let (tx_02, rx_02) = mpsc::channel();
let tx_02_clone: std::sync::mpsc::Sender<(SystemTime, SystemTime, Vec<String>, SystemTime)> = tx_02.clone();
let d: Vec<Vec<String>> = vec![
vec!["01".to_string(), "02".to_string(), "03".to_string()],
vec!["04".to_string(), "05".to_string(), "06".to_string()],
vec!["07".to_string(), "08".to_string(), "09".to_string()],
vec!["10".to_string(), "11".to_string(), "12".to_string()]
];
let mut arch: Vec<(SystemTime, SystemTime, Vec<String>, SystemTime, SystemTime)> = vec![];
DataSR::sr(rx_01, tx_02_clone);
drop(tx_01);
drop(tx_02); // ? does not affect operation
let mut index_d: u16 = 0;
let mut t_send: u64 = SystemTime::now().duration_since(UNIX_EPOCH).expect("..info").as_secs();
let mut t_now = SystemTime::now();
println!("start from main: {:?}", sys_hmsn(&t_now, 2));
let mut flag_break = 1;
loop {
// SEND from main to child (every 3 seconds):
if index_d == d.len() as u16 { flag_break = 0; }
t_now = SystemTime::now();
if t_send + 3 <= t_now.duration_since(UNIX_EPOCH).expect("..info").as_secs() {
t_send = t_send + 3;
println!("index_d = {:?}", index_d);
let _ = tx_01_clone.send((t_now, d[index_d as usize].clone()));
index_d = index_d + 1;
}
// RECEIVED from child:
if let Ok(val) = &rx_02.try_recv() {
arch.push((val.0, val.1, val.2.clone(), val.3, SystemTime::now()));
if flag_break == 0 { break; }
};
}
println!("\n[send from main] - [rec in child] - [data] - [send from child] - [rec in main]\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
for val in &arch {
if val.0 == SystemTime::UNIX_EPOCH {
println!(" {:?} - [{}] - [{}]", &val.2, sys_hmsn(&val.3, 2), sys_hmsn(&val.4, 2));
} else {
println!("[{}] - [{}] - {:?} - [{}] - [{}]", sys_hmsn(&val.0, 2), sys_hmsn(&val.1, 2), &val.2, sys_hmsn(&val.3, 2), sys_hmsn(&val.4, 2));
}
}
// println!("\narch = {:?}\n", &arch);
}
fn sys_hmsn(now: &SystemTime, time_zone: u64) -> String {
match now.duration_since(UNIX_EPOCH) {
Ok(duration) => {
let total_seconds = duration.as_secs();
let nanoseconds = duration.subsec_nanos(); // Nanoseconds part within the last second
let hour = (total_seconds / 60 / 60 + time_zone) % 24;
let minute = (total_seconds / 60) % 60;
let second = total_seconds % 60;
hour.to_string() + &":".to_string() + &minute.to_string() + &":".to_string() + &second.to_string() + &".".to_string() + &nanoseconds.to_string()
},
Err(e) => "System time error: ".to_string() + &e.to_string()
}
}
txrx.rs
use std::thread;
use std::time::{SystemTime, UNIX_EPOCH};
use std::sync::mpsc::Receiver;
use crate::sys_hmsn;
pub struct DataSR;
impl DataSR {
pub fn sr(rx_01: Receiver<(SystemTime, Vec<String>)>, tx_02_clone: std::sync::mpsc::Sender<(SystemTime, SystemTime, Vec<String>, SystemTime)>) {
thread::spawn(move || {
let mut data: (SystemTime, SystemTime, Vec<String>, SystemTime) = (SystemTime::UNIX_EPOCH, SystemTime::UNIX_EPOCH, vec![], SystemTime::UNIX_EPOCH); // = Default::default();
let mut t_now_child: SystemTime = SystemTime::now();
println!("start from child: {:?}", sys_hmsn(&t_now_child, 2));
let mut t_send_child: u64 = SystemTime::now().duration_since(UNIX_EPOCH).expect("..info").as_secs();
let mut d_child = vec![];
loop {
// SEND from child to main (every 2 seconds):
t_now_child = SystemTime::now();
if t_send_child + 2 <= t_now_child.duration_since(UNIX_EPOCH).expect("..info").as_secs() {
t_send_child = t_send_child + 2;
if let Ok(val) = rx_01.try_recv() { // rx_01.recv_timeout(Duration::from_millis(2000))
t_now_child = SystemTime::now();
data.0 = val.0; // systemtime: send from main;
data.1 = t_now_child; // systemtime: received in child;
data.2 = val.1; // data
data.3 = SystemTime::now(); // systemtime: send from child;
tx_02_clone.send(data.clone()).unwrap();// send data to the main thread;
d_child = data.2;
} else {
data.0 = SystemTime::UNIX_EPOCH;
data.1 = SystemTime::UNIX_EPOCH;
data.2 = d_child.clone();
data.3 = SystemTime::now();
tx_02_clone.send(data.clone()).unwrap();// send data to the main thread;
// println!(" ~ [{:?}] - []", sys_hmsn(&t_now_child, 2));
}
}
}
});
}
}
Report
start from main: "12:14:59.525580200"
start from child: "12:14:59.525707500"
index_d = 0
index_d = 1
index_d = 2
index_d = 3
[send from main] - [rec in child] - [data] - [send from child] - [rec in main]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[] - [12:15:1.4500] - [12:15:1.25500]
[12:15:2.0] - [12:15:3.2400] - ["01", "02", "03"] - [12:15:3.3300] - [12:15:3.16500]
["01", "02", "03"] - [12:15:5.8300] - [12:15:5.196700]
[12:15:5.0] - [12:15:7.2600] - ["04", "05", "06"] - [12:15:7.5800] - [12:15:7.19000]
[12:15:8.0] - [12:15:9.1500] - ["07", "08", "09"] - [12:15:9.1600] - [12:15:9.13700]
["07", "08", "09"] - [12:15:11.5100] - [12:15:11.217900]
[12:15:11.0] - [12:15:13.1700] - ["10", "11", "12"] - [12:15:13.4800] - [12:15:13.12900]
arch =
[
(SystemTime { intervals: 116444736000000000 }, SystemTime { intervals: 116444736000000000 }, [], SystemTime { intervals: 134180433010000045 }, SystemTime { intervals: 134180433010000255 }),
(SystemTime { intervals: 134180433020000000 }, SystemTime { intervals: 134180433030000024 }, ["01", "02", "03"], SystemTime { intervals: 134180433030000033 }, SystemTime { intervals: 134180433030000165 }),
(SystemTime { intervals: 116444736000000000 }, SystemTime { intervals: 116444736000000000 }, ["01", "02", "03"], SystemTime { intervals: 134180433050000083 }, SystemTime { intervals: 134180433050001967 }),
(SystemTime { intervals: 134180433050000000 }, SystemTime { intervals: 134180433070000026 }, ["04", "05", "06"], SystemTime { intervals: 134180433070000058 }, SystemTime { intervals: 134180433070000190 }),
(SystemTime { intervals: 134180433080000000 }, SystemTime { intervals: 134180433090000015 }, ["07", "08", "09"], SystemTime { intervals: 134180433090000016 }, SystemTime { intervals: 134180433090000137 }),
(SystemTime { intervals: 116444736000000000 }, SystemTime { intervals: 116444736000000000 }, ["07", "08", "09"], SystemTime { intervals: 134180433110000051 }, SystemTime { intervals: 134180433110002179 }),
(SystemTime { intervals: 134180433110000000 }, SystemTime { intervals: 134180433130000017 }, ["10", "11", "12"], SystemTime { intervals: 134180433130000048 }, SystemTime { intervals: 134180433130000129 })
]
解决方案
你不需要变量 data,因为你在循环内已经完全重新赋值了它。此外,由于你没有对它们进行修改,你可以将你的 Vec<String> 替换为 Arc<[String]>,它是廉价可克隆的(因为克隆它只涉及增加引用计数,而不复制实际数据):
use std::sync::Arc;
use std::sync::mpsc;
use std::sync::mpsc::Receiver;
use std::thread;
use std::time::{SystemTime, UNIX_EPOCH};
struct DataSR;
impl DataSR {
pub fn sr(
rx_01: Receiver<(SystemTime, Arc<[String]>)>,
tx_02_clone: std::sync::mpsc::Sender<(SystemTime, SystemTime, Arc<[String]>, SystemTime)>,
) {
thread::spawn(move || {
//let mut data: (SystemTime, SystemTime, Vec<String>, SystemTime) = (SystemTime::UNIX_EPOCH, SystemTime::UNIX_EPOCH, vec![], SystemTime::UNIX_EPOCH); // = Default::default();
let mut t_now_child: SystemTime = SystemTime::now();
println!("start from child: {:?}", sys_hmsn(&t_now_child, 2));
let mut t_send_child: u64 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("..info")
.as_secs(); // секунды в u64;
let mut d_child = Arc::from(vec![]);
loop {
// SEND from child to main (every 2 seconds):
t_now_child = SystemTime::now();
if t_send_child + 2
<= t_now_child
.duration_since(UNIX_EPOCH)
.expect("..info")
.as_secs()
{
t_send_child = t_send_child + 2;
if let Ok(val) = rx_01.try_recv() {
// rx_01.recv_timeout(Duration::from_millis(2000))
t_now_child = SystemTime::now();
d_child = val.1.clone();
tx_02_clone
.send((val.0, t_now_child, val.1, SystemTime::now()))
.unwrap(); // send data to the main thread;
} else {
tx_02_clone
.send((
SystemTime::UNIX_EPOCH,
SystemTime::UNIX_EPOCH,
d_child.clone(),
SystemTime::now(),
))
.unwrap(); // send data to the main thread;
// println!(" ~ [{:?}] - []", sys_hmsn(&t_now_child, 2));
}
}
}
});
}
}
fn main() {
let (tx_01, rx_01) = mpsc::channel();
let (tx_02, rx_02) = mpsc::channel();
let d: Vec<Arc<[String]>> = vec![
Arc::from(vec!["01".to_string(), "02".to_string(), "03".to_string()]),
Arc::from(vec!["04".to_string(), "05".to_string(), "06".to_string()]),
Arc::from(vec!["07".to_string(), "08".to_string(), "09".to_string()]),
Arc::from(vec!["10".to_string(), "11".to_string(), "12".to_string()]),
];
let mut arch: Vec<(
SystemTime,
SystemTime,
Arc<[String]>,
SystemTime,
SystemTime,
)> = vec![];
DataSR::sr(rx_01, tx_02);
let mut index_d: u16 = 0;
let mut t_send: u64 = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("..info")
.as_secs();
let mut t_now = SystemTime::now();
println!("start from main: {:?}", sys_hmsn(&t_now, 2));
let mut flag_break = 1;
loop {
// SEND from main to child (every 3 seconds):
if index_d == d.len() as u16 {
flag_break = 0;
}
t_now = SystemTime::now();
if t_send + 3 <= t_now.duration_since(UNIX_EPOCH).expect("..info").as_secs() {
t_send = t_send + 3;
println!("index_d = {:?}", index_d);
let _ = tx_01.send((t_now, d[index_d as usize].clone()));
index_d = index_d + 1;
}
// RECEIVED from child:
if let Ok(val) = &rx_02.try_recv() {
arch.push((val.0, val.1, val.2.clone(), val.3, SystemTime::now()));
if flag_break == 0 {
break;
}
};
}
println!("\n[send from main] - [rec in child] - [data] - [send from child] - [rec in main]\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
for val in &arch {
if val.0 == SystemTime::UNIX_EPOCH {
println!(
" {:?} - [{}] - [{}]",
&val.2,
sys_hmsn(&val.3, 2),
sys_hmsn(&val.4, 2)
);
} else {
println!(
"[{}] - [{}] - {:?} - [{}] - [{}]",
sys_hmsn(&val.0, 2),
sys_hmsn(&val.1, 2),
&val.2,
sys_hmsn(&val.3, 2),
sys_hmsn(&val.4, 2)
);
}
}
// println!("\narch = {:?}\n", &arch);
}
fn sys_hmsn(now: &SystemTime, time_zone: u64) -> String {
match now.duration_since(UNIX_EPOCH) {
Ok(duration) => {
let total_seconds = duration.as_secs();
let nanoseconds = duration.subsec_nanos(); // Nanoseconds part within the last second
let hour = (total_seconds / 60 / 60 + time_zone) % 24;
let minute = (total_seconds / 60) % 60;
let second = total_seconds % 60;
hour.to_string()
+ &":".to_string()
+ &minute.to_string()
+ &":".to_string()
+ &second.to_string()
+ &".".to_string()
+ &nanoseconds.to_string()
}
Err(e) => "System time error: ".to_string() + &e.to_string(),
}
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。