main.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. use std::collections::HashMap;
  2. use std::{error::Error, fs::File, io, io::Write, process};
  3. use serde::Deserialize;
  4. #[derive(Debug, Deserialize)]
  5. struct Record {
  6. _hr_time: String,
  7. time: f64, // FIXME: use a better type, either a real datetime or our own two ints
  8. user: String,
  9. group: String,
  10. action_data: Vec<String>,
  11. }
  12. struct RunningValue {
  13. sent_count: u32,
  14. receipt_count: u32,
  15. running_rtt_mean: f64,
  16. }
  17. fn core(path: Option<String>) -> Result<(), Box<dyn Error>> {
  18. let mut rtt_all_file = File::create("rtt_all.mgen.json")?;
  19. writeln!(rtt_all_file, "[")?;
  20. let mut sent_times: HashMap<(String, String, u32), f64> = HashMap::new();
  21. let mut running_values: HashMap<(String, String), RunningValue> = HashMap::new();
  22. let file: Box<dyn io::Read> = if let Some(path) = path {
  23. Box::new(File::open(path)?)
  24. } else {
  25. Box::new(io::stdin())
  26. };
  27. let mut rdr = csv::ReaderBuilder::new()
  28. .has_headers(false)
  29. .flexible(true)
  30. .from_reader(file);
  31. for result in rdr.deserialize() {
  32. let record: Record = result?;
  33. match record.action_data[0].as_str() {
  34. "send" => {
  35. let id = record.action_data[4].parse()?;
  36. sent_times.insert((record.user.clone(), record.group.clone(), id), record.time);
  37. running_values
  38. .entry((record.user, record.group))
  39. .and_modify(|running_value| running_value.sent_count += 1)
  40. .or_insert(RunningValue {
  41. sent_count: 1,
  42. receipt_count: 0,
  43. running_rtt_mean: 0.0,
  44. });
  45. }
  46. "receive" => {
  47. if record.action_data[4] == "receipt" {
  48. let id = record.action_data[5].parse()?;
  49. let key = (record.user, record.group, id);
  50. let Some(sent_time) = sent_times.get(&key) else {
  51. // this should never happen in the client-server case,
  52. // but we filter out early conversation in the p2p case
  53. //eprintln!("receipt for unknown message: {:?}", key);
  54. //panic!();
  55. continue;
  56. };
  57. let rtt = record.time - sent_time;
  58. writeln!(rtt_all_file, " {},", rtt)?;
  59. let key = (key.0, key.1);
  60. running_values.entry(key).and_modify(|running_value| {
  61. running_value.receipt_count += 1;
  62. running_value.running_rtt_mean = running_value.running_rtt_mean
  63. + (rtt - running_value.running_rtt_mean)
  64. / (running_value.receipt_count as f64);
  65. });
  66. }
  67. }
  68. _ => (),
  69. }
  70. }
  71. writeln!(rtt_all_file, "]")?;
  72. drop(rtt_all_file);
  73. let mut rtt_count_file = File::create("counts.mgen.json")?;
  74. let mut rtt_mean_file = File::create("rtt_mean.mgen.json")?;
  75. writeln!(rtt_count_file, "[")?;
  76. writeln!(rtt_mean_file, "[")?;
  77. for value in running_values.into_values() {
  78. writeln!(rtt_count_file, " {},", value.sent_count)?;
  79. writeln!(rtt_mean_file, " {},", value.running_rtt_mean)?;
  80. }
  81. writeln!(rtt_count_file, "]")?;
  82. writeln!(rtt_mean_file, "]")?;
  83. Ok(())
  84. }
  85. fn main() {
  86. let mut args = std::env::args();
  87. let _ = args.next();
  88. let path = args.next();
  89. if let Err(err) = core(path) {
  90. println!("error running example: {}", err);
  91. process::exit(1);
  92. }
  93. }