Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,202 @@
|
||||
use indexmap::IndexMap;
|
||||
|
||||
struct Lookup {
|
||||
generated: Map<Id, i64>,
|
||||
reference: IndexMap<Id, i64>,
|
||||
keys: Vec<Id>,
|
||||
}
|
||||
|
||||
struct Comparison {
|
||||
values: Vec<Id>,
|
||||
expected: Id,
|
||||
}
|
||||
|
||||
fn id_fault() -> Fault {
|
||||
&FaultInfo {
|
||||
message: "integer arithmetic fault",
|
||||
source: "reference.dever",
|
||||
line: 1,
|
||||
column: 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn roundtrip_generated(values: &[String]) -> Result<String, Fault> {
|
||||
GENERATED_ROUNDTRIP(values.first().map(String::as_str).unwrap_or(""))
|
||||
}
|
||||
|
||||
fn roundtrip_reference(values: &[String]) -> Result<String, Fault> {
|
||||
let id = Id::from(values.first().map(String::as_str).unwrap_or("").to_owned());
|
||||
Ok(id.into_text())
|
||||
}
|
||||
|
||||
fn encode_reference(values: &[String]) -> Result<Vec<Id>, Fault> {
|
||||
Ok(values.iter().map(|text| Id::from(text.clone())).collect())
|
||||
}
|
||||
|
||||
fn compare_generated(values: &[Comparison]) -> Result<i64, Fault> {
|
||||
match values.first() {
|
||||
Some(value) => GENERATED_COMPARE(&value.values, &value.expected),
|
||||
None => Ok(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_reference(values: &[Comparison]) -> Result<i64, Fault> {
|
||||
let Some(value) = values.first() else {
|
||||
return Ok(0);
|
||||
};
|
||||
let expected = value.expected.clone();
|
||||
let mut count = 0i64;
|
||||
for item in &value.values {
|
||||
count = count
|
||||
.checked_add(i64::from(item == &expected))
|
||||
.ok_or_else(id_fault)?;
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
fn lookup_generated(values: &[Lookup]) -> Result<i64, Fault> {
|
||||
match values.first() {
|
||||
Some(value) => GENERATED_LOOKUP(&value.generated, &value.keys),
|
||||
None => Ok(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_reference(values: &[Lookup]) -> Result<i64, Fault> {
|
||||
let Some(value) = values.first() else {
|
||||
return Ok(0);
|
||||
};
|
||||
let mut count = 0i64;
|
||||
for key in &value.keys {
|
||||
count = count
|
||||
.checked_add(value.reference.get(key).copied().unwrap_or(0))
|
||||
.ok_or_else(id_fault)?;
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
fn lookup_same_table(values: &[Lookup]) -> Result<i64, Fault> {
|
||||
let Some(value) = values.first() else {
|
||||
return Ok(0);
|
||||
};
|
||||
let mut count = 0i64;
|
||||
for key in &value.keys {
|
||||
count = count
|
||||
.checked_add(value.generated.get(key).copied().unwrap_or(0))
|
||||
.ok_or_else(id_fault)?;
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
fn map_reference(values: &[String]) -> Result<Vec<(Id, i64)>, Fault> {
|
||||
let mut map = IndexMap::new();
|
||||
for text in values {
|
||||
map.insert(Id::from(text.clone()), text.chars().count() as i64);
|
||||
}
|
||||
Ok(map.into_iter().collect())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let texts: Vec<String> = (0..512)
|
||||
.map(|index| format!("user-{index:04}-雪"))
|
||||
.collect();
|
||||
let short = ["user-0012-雪".to_owned()];
|
||||
let long = ["雪山树林".repeat(512)];
|
||||
let reference = || {
|
||||
texts
|
||||
.iter()
|
||||
.map(|text| (Id::from(text.clone()), text.chars().count() as i64))
|
||||
.collect()
|
||||
};
|
||||
// 建表顺序影响独立表的哈希与分配布局;复测须等量覆盖两种顺序。
|
||||
let (generated, reference) = match std::env::var("DEVER_BENCH_MAP_ORDER")
|
||||
.as_deref()
|
||||
.unwrap_or("dever-first")
|
||||
{
|
||||
"dever-first" => {
|
||||
let generated = GENERATED_BUILD_MAP(&texts).unwrap();
|
||||
(generated, reference())
|
||||
}
|
||||
"rust-first" => {
|
||||
let reference = reference();
|
||||
(GENERATED_BUILD_MAP(&texts).unwrap(), reference)
|
||||
}
|
||||
order => panic!("unknown table construction order: {order}"),
|
||||
};
|
||||
let keys = (0..1024)
|
||||
.map(|index| Id::from(format!("user-{:04}-雪", (index * 17) % 576)))
|
||||
.collect();
|
||||
let lookups = [Lookup {
|
||||
generated,
|
||||
reference,
|
||||
keys,
|
||||
}];
|
||||
let comparisons = [Comparison {
|
||||
values: (0..1024)
|
||||
.map(|index| Id::from(format!("user-{:04}-雪", index % 32)))
|
||||
.collect(),
|
||||
expected: Id::from("user-0012-雪".to_owned()),
|
||||
}];
|
||||
assert_eq!(
|
||||
GENERATED_ENTRIES(&["a".into(), "b".into(), "a".into()]).unwrap(),
|
||||
map_reference(&["a".into(), "b".into(), "a".into()]).unwrap()
|
||||
);
|
||||
println!("case,sample,implementation,elapsed_ns,checksum");
|
||||
compare(
|
||||
"id_roundtrip_short",
|
||||
&short,
|
||||
300000,
|
||||
roundtrip_generated,
|
||||
roundtrip_reference,
|
||||
|value| value.len() as u64,
|
||||
);
|
||||
compare(
|
||||
"id_roundtrip_long",
|
||||
&long,
|
||||
20000,
|
||||
roundtrip_generated,
|
||||
roundtrip_reference,
|
||||
|value| value.len() as u64,
|
||||
);
|
||||
compare(
|
||||
"id_each",
|
||||
&texts,
|
||||
300,
|
||||
GENERATED_ENCODE_ALL,
|
||||
encode_reference,
|
||||
|value| value.len() as u64,
|
||||
);
|
||||
compare(
|
||||
"id_compare",
|
||||
&comparisons,
|
||||
2000,
|
||||
compare_generated,
|
||||
compare_reference,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
"id_map_lookup",
|
||||
&lookups,
|
||||
1000,
|
||||
lookup_generated,
|
||||
lookup_reference,
|
||||
|value| *value as u64,
|
||||
);
|
||||
// 双方读取同一张表,避免将各自随机哈希状态的差异归给生成代码。
|
||||
compare_named(
|
||||
"id_map_lookup_same_table",
|
||||
&lookups,
|
||||
1000,
|
||||
lookup_generated,
|
||||
lookup_same_table,
|
||||
|value| *value as u64,
|
||||
"rust_runtime",
|
||||
);
|
||||
compare(
|
||||
"id_map_build",
|
||||
&texts,
|
||||
300,
|
||||
GENERATED_ENTRIES,
|
||||
map_reference,
|
||||
|value| value.len() as u64,
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user