Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,306 @@
|
||||
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}");
|
||||
}
|
||||
Reference in new issue
Block a user