Files
core/test/performance/fixtures/kernel/peer.rs
T
2026-11-03 03:32:07 +00:00

307 lines
10 KiB
Rust

use indexmap::IndexMap;
use std::hint::black_box;
use std::time::Instant;
struct Record {
first: i64,
second: i64,
third: i64,
}
struct OwnedRecord {
name: String,
tags: Vec<String>,
count: i64,
}
fn inspect_owned(row: &OwnedRecord) -> i64 {
add(
add(row.count, row.name.chars().count() as i64),
row.tags.len() as i64,
)
}
fn forward_owned(row: &OwnedRecord) -> i64 {
inspect_owned(row)
}
fn add(total: i64, value: i64) -> i64 {
total.checked_add(value).expect("integer overflow")
}
fn record_value(row: &Record) -> i64 {
add(add(row.first, row.second), row.third)
}
fn measure(operation: &str, ticks: &str) -> serde_json::Value {
let source = black_box(ticks.as_bytes());
let (checksum, elapsed) = match operation {
"record_update" => {
let begin = Instant::now();
let mut values = Vec::new();
let mut count = 0;
for value in source {
values.push(i64::from(*value));
count = add(count, 1);
}
black_box((&values, count));
let elapsed = begin.elapsed();
let total = values.iter().fold(0, |total, value| add(total, *value));
let checksum = add(total, count)
.checked_sub(values.len() as i64)
.expect("integer overflow");
(checksum, elapsed)
}
"record_inspect" => {
let begin = Instant::now();
let mut values = Vec::new();
let mut count = 0;
for value in source {
count = add(values.len() as i64, 1);
values.push(i64::from(*value));
}
black_box((&values, count));
let elapsed = begin.elapsed();
let total = values.iter().fold(0, |total, value| add(total, *value));
let checksum = add(total, count)
.checked_sub(values.len() as i64)
.expect("integer overflow");
(checksum, elapsed)
}
"map_lookup" => {
let values = source
.iter()
.enumerate()
.map(|(index, value)| (index as i64, i64::from(*value)))
.collect::<IndexMap<_, _>>();
let borrowed = black_box(&values);
let mut index = 0;
let mut total = 0;
let begin = Instant::now();
for _ in source {
total = add(total, borrowed.get(&index).copied().unwrap_or(0));
index = add(index, 1);
}
black_box(total);
let elapsed = begin.elapsed();
black_box(&values);
(total, elapsed)
}
"text_equal" | "text_contains" => {
let rows = source
.iter()
.map(|value| {
let left = format!("compare-value-{value}");
let right = left.to_uppercase().to_lowercase();
(left, right)
})
.collect::<Vec<_>>();
let borrowed = black_box(&rows);
let mut total = 0;
let begin = Instant::now();
if operation == "text_equal" {
for (left, right) in borrowed {
total = add(total, if left == right { 120 } else { 0 });
}
} else {
for (left, right) in borrowed {
total = add(
total,
if left.contains(right.as_str()) {
120
} else {
0
},
);
}
}
black_box(total);
let elapsed = begin.elapsed();
black_box(&rows);
let checksum = add(total, rows.len() as i64)
.checked_sub(source.len() as i64)
.expect("integer overflow");
(checksum, elapsed)
}
"map_text_lookup" => {
// 与 Dever 使用相同的拥有键和插入顺序;HashMap<&str, _> 是不同的数据结构。
let values = source
.iter()
.enumerate()
.map(|(index, value)| (format!("lookup-key-{index}"), i64::from(*value)))
.collect::<IndexMap<_, _>>();
let keys = values.keys().cloned().collect::<Vec<_>>();
let borrowed = black_box(&values);
let mut total = 0;
let begin = Instant::now();
for key in &keys {
total = add(total, borrowed.get(key.as_str()).copied().unwrap_or(0));
}
black_box(total);
let elapsed = begin.elapsed();
black_box((&keys, &values));
let checksum = add(total, keys.len() as i64)
.checked_sub(source.len() as i64)
.expect("integer overflow");
(checksum, elapsed)
}
"call_read" => {
let rows = source
.iter()
.map(|value| {
let name = format!("row-value-{value}");
OwnedRecord {
count: i64::from(*value) - name.chars().count() as i64 - 1,
tags: vec![name.clone()],
name,
}
})
.collect::<Vec<_>>();
let borrowed = black_box(&rows);
let begin = Instant::now();
let total = borrowed
.iter()
.fold(0, |total, row| add(total, forward_owned(row)));
black_box(total);
let elapsed = begin.elapsed();
black_box(&rows);
(total, elapsed)
}
"float" => {
let begin = Instant::now();
let total = source
.iter()
.fold(0.0, |total, value| total + f64::from(*value));
black_box(total);
let elapsed = begin.elapsed();
(total as i64, elapsed)
}
"bytes_concat" => {
let chunks = source.chunks(1).map(<[u8]>::to_vec).collect::<Vec<_>>();
let begin = Instant::now();
let mut output = Vec::new();
for chunk in &chunks {
output.extend_from_slice(chunk);
}
black_box(&output);
let elapsed = begin.elapsed();
drop(chunks);
let total = output
.iter()
.fold(0, |total, byte| add(total, i64::from(*byte)));
(total, elapsed)
}
"text_concat" => {
let chunks = std::str::from_utf8(source)
.unwrap()
.split(',')
.map(str::to_owned)
.collect::<Vec<_>>();
let begin = Instant::now();
let mut output = String::new();
for chunk in &chunks {
output.push_str(chunk);
}
black_box(&output);
let elapsed = begin.elapsed();
drop(chunks);
let total = output
.bytes()
.fold(0, |total, byte| add(total, i64::from(byte)));
(total, elapsed)
}
"integer" => {
let begin = Instant::now();
let total = source
.iter()
.fold(0, |total, value| add(total, i64::from(*value)));
(black_box(total), begin.elapsed())
}
"list" | "list_read" => {
let mut values = Vec::new();
let begin = Instant::now();
values.extend(source.iter().map(|value| i64::from(*value)));
let construction = begin.elapsed();
let borrowed = black_box(&values);
let begin = Instant::now();
let total = borrowed.iter().fold(0, |total, value| add(total, *value));
black_box(total);
let traversal = begin.elapsed();
drop(values);
(
total,
if operation == "list" {
construction
} else {
traversal
},
)
}
"list_record" | "list_record_read" => {
let mut values = Vec::new();
let begin = Instant::now();
for value in source {
values.push(Record {
first: i64::from(*value),
second: 0,
third: 0,
});
}
let construction = begin.elapsed();
let borrowed = black_box(&values);
let begin = Instant::now();
let total = borrowed
.iter()
.fold(0, |total, row| add(total, record_value(row)));
black_box(total);
let traversal = begin.elapsed();
drop(values);
(
total,
if operation == "list_record" {
construction
} else {
traversal
},
)
}
"map" | "map_read" => {
let mut values = IndexMap::new();
let begin = Instant::now();
for value in source {
let key = i64::try_from(values.len()).expect("map size");
values.insert(key, i64::from(*value));
}
let construction = begin.elapsed();
let borrowed = black_box(&values);
let begin = Instant::now();
let total = borrowed.values().fold(0, |total, value| add(total, *value));
black_box(total);
drop(values);
let traversal = begin.elapsed();
(
total,
if operation == "map" {
construction
} else {
traversal
},
)
}
_ => panic!("unknown kernel"),
};
serde_json::json!({"checksum": checksum, "elapsed_ns": elapsed.as_nanos()})
}
fn main() {
let arguments = std::env::args().collect::<Vec<_>>();
let input: serde_json::Value = serde_json::from_str(&arguments[2]).expect("input object");
let ticks = input["ticks"].as_str().expect("ticks string");
let output = if let Some(operation) = arguments[1].strip_prefix("continuous_") {
serde_json::Value::Array((0..10).map(|_| measure(operation, ticks)).collect())
} else {
measure(&arguments[1], ticks)
};
println!("{output}");
}