Initial Dever 0.0.1
This commit is contained in:
commit
81233d098c
1479 files changed
+163782
No files matched your search
@@ -0,0 +1,355 @@
|
||||
use indexmap::IndexMap;
|
||||
|
||||
fn map_fault() -> Fault {
|
||||
&FaultInfo {
|
||||
message: "integer overflow",
|
||||
source: "map-reference",
|
||||
line: 1,
|
||||
column: 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn add(total: i64, value: i64) -> Result<i64, Fault> {
|
||||
total.checked_add(value).ok_or_else(map_fault)
|
||||
}
|
||||
|
||||
fn build_text(values: &[String]) -> IndexMap<String, String> {
|
||||
let mut map = IndexMap::with_capacity(values.len());
|
||||
for value in values {
|
||||
map.insert(value.clone(), value.clone());
|
||||
}
|
||||
map
|
||||
}
|
||||
|
||||
fn build_nested(values: &[String]) -> IndexMap<String, Vec<String>> {
|
||||
let mut map = IndexMap::with_capacity(values.len());
|
||||
for value in values {
|
||||
map.insert(value.clone(), vec![value.clone(), value.clone()]);
|
||||
}
|
||||
map
|
||||
}
|
||||
|
||||
fn text_weight(key: &str, value: &str) -> Result<i64, Fault> {
|
||||
add(key.chars().count() as i64, value.chars().count() as i64)
|
||||
}
|
||||
|
||||
fn nested_weight(key: &str, values: &[String]) -> Result<i64, Fault> {
|
||||
let count = values
|
||||
.iter()
|
||||
.try_fold(0, |total, value| add(total, value.chars().count() as i64))?;
|
||||
add(key.chars().count() as i64, count)
|
||||
}
|
||||
|
||||
fn owned_text(values: &[String]) -> Result<i64, Fault> {
|
||||
build_text(values)
|
||||
.into_iter()
|
||||
.try_fold(0, |total, (key, value)| {
|
||||
add(total, text_weight(&key, &value)?)
|
||||
})
|
||||
}
|
||||
|
||||
fn owned_nested(values: &[String]) -> Result<i64, Fault> {
|
||||
build_nested(values)
|
||||
.into_iter()
|
||||
.try_fold(0, |total, (key, value)| {
|
||||
add(total, nested_weight(&key, &value)?)
|
||||
})
|
||||
}
|
||||
|
||||
struct Borrowed {
|
||||
text: Map<String, String>,
|
||||
nested: Map<String, Vec<String>>,
|
||||
reference_text: IndexMap<String, String>,
|
||||
reference_nested: IndexMap<String, Vec<String>>,
|
||||
}
|
||||
|
||||
fn borrowed_text(values: &[Borrowed]) -> Result<i64, Fault> {
|
||||
values
|
||||
.first()
|
||||
.map_or(Ok(0), |value| GENERATED_BORROWED_TEXT(&value.text))
|
||||
}
|
||||
|
||||
fn borrowed_nested(values: &[Borrowed]) -> Result<i64, Fault> {
|
||||
values
|
||||
.first()
|
||||
.map_or(Ok(0), |value| GENERATED_BORROWED_NESTED(&value.nested))
|
||||
}
|
||||
|
||||
fn reference_borrowed_text(values: &[Borrowed]) -> Result<i64, Fault> {
|
||||
values.first().map_or(Ok(0), |value| {
|
||||
value
|
||||
.reference_text
|
||||
.iter()
|
||||
.try_fold(0, |total, (key, value)| {
|
||||
add(total, text_weight(key, value)?)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 原始参照合并了两个错误来源;分别保留故障位置,并用同一张表排除输入地址差异。
|
||||
fn reference_text_same_faults<const SHARED: bool>(values: &[Borrowed]) -> Result<i64, Fault> {
|
||||
values.first().map_or(Ok(0), |value| {
|
||||
let mut entries = if SHARED {
|
||||
value.text.iter()
|
||||
} else {
|
||||
value.reference_text.iter()
|
||||
};
|
||||
entries.try_fold(0i64, |total, (key, value)| {
|
||||
let count = (key.chars().count() as i64)
|
||||
.checked_add(value.chars().count() as i64)
|
||||
.ok_or(const {
|
||||
&FaultInfo {
|
||||
message: "integer arithmetic fault",
|
||||
source: "map-reference",
|
||||
line: 1,
|
||||
column: 1,
|
||||
}
|
||||
})?;
|
||||
total.checked_add(count).ok_or(const {
|
||||
&FaultInfo {
|
||||
message: "integer overflow",
|
||||
source: "map-reference",
|
||||
line: 2,
|
||||
column: 1,
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn reference_borrowed_nested(values: &[Borrowed]) -> Result<i64, Fault> {
|
||||
values.first().map_or(Ok(0), |value| {
|
||||
value
|
||||
.reference_nested
|
||||
.iter()
|
||||
.try_fold(0, |total, (key, value)| {
|
||||
add(total, nested_weight(key, value)?)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn reference_nested_same_order(values: &[Borrowed]) -> Result<i64, Fault> {
|
||||
values.first().map_or(Ok(0), |value| {
|
||||
value
|
||||
.reference_nested
|
||||
.iter()
|
||||
.try_fold(0, |total, (key, values)| {
|
||||
let key_count = key.chars().count() as i64;
|
||||
let count = values
|
||||
.iter()
|
||||
.try_fold(0, |total, value| add(total, value.chars().count() as i64))?;
|
||||
add(total, add(key_count, count)?)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn reference_nested_same_faults<const SHARED: bool>(values: &[Borrowed]) -> Result<i64, Fault> {
|
||||
values.first().map_or(Ok(0), |value| {
|
||||
let mut entries = if SHARED {
|
||||
value.nested.iter()
|
||||
} else {
|
||||
value.reference_nested.iter()
|
||||
};
|
||||
entries.try_fold(0i64, |total, (key, values)| {
|
||||
let key_count = key.chars().count() as i64;
|
||||
let count = values.iter().try_fold(0i64, |total, value| {
|
||||
total.checked_add(value.chars().count() as i64).ok_or(
|
||||
const {
|
||||
&FaultInfo {
|
||||
message: "integer overflow",
|
||||
source: "map-reference",
|
||||
line: 1,
|
||||
column: 1,
|
||||
}
|
||||
},
|
||||
)
|
||||
})?;
|
||||
let count = key_count.checked_add(count).ok_or(
|
||||
const {
|
||||
&FaultInfo {
|
||||
message: "integer arithmetic fault",
|
||||
source: "map-reference",
|
||||
line: 2,
|
||||
column: 1,
|
||||
}
|
||||
},
|
||||
)?;
|
||||
total.checked_add(count).ok_or(
|
||||
const {
|
||||
&FaultInfo {
|
||||
message: "integer overflow",
|
||||
source: "map-reference",
|
||||
line: 3,
|
||||
column: 1,
|
||||
}
|
||||
},
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn list_first(values: &[String]) -> Result<Option<String>, Fault> {
|
||||
values
|
||||
.first()
|
||||
.map_or(Ok(None), |value| GENERATED_LIST_FIRST(value))
|
||||
}
|
||||
|
||||
// 两个实现逐个读取同一批表,避免把某一份输入的分配位置固定给一个标签。
|
||||
fn nested_corpus<const GENERATED: bool>(values: &[Borrowed]) -> Result<i64, Fault> {
|
||||
let mut total = 0i64;
|
||||
for value in values {
|
||||
let input = std::slice::from_ref(value);
|
||||
let count = if GENERATED {
|
||||
borrowed_nested(input)?
|
||||
} else {
|
||||
reference_nested_same_faults::<true>(input)?
|
||||
};
|
||||
total = add(total, count)?;
|
||||
}
|
||||
Ok(total)
|
||||
}
|
||||
|
||||
// 已知字面量的选取等价于复制输入,独立 Rust 直接实现这一结果。
|
||||
fn reference_owned_text(values: &[String]) -> Result<Option<String>, Fault> {
|
||||
values.first().map_or(Ok(None), |value| {
|
||||
let value = value.as_str();
|
||||
Ok(Some(value.to_owned()))
|
||||
})
|
||||
}
|
||||
|
||||
fn map_get(values: &[String]) -> Result<Option<String>, Fault> {
|
||||
values
|
||||
.first()
|
||||
.map_or(Ok(None), |value| GENERATED_MAP_GET(value))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("case,sample,implementation,elapsed_ns,checksum");
|
||||
let reference_first = std::env::var_os("DEVER_MAP_REFERENCE_FIRST").is_some();
|
||||
for size in [32, 4096] {
|
||||
let values: Vec<String> = (0..64)
|
||||
.map(|index| format!("{index}:{}", "雪".repeat(size / 3)))
|
||||
.collect();
|
||||
// 两种建表顺序都计时;同表参照另行保留,排除独立分配地址的影响。
|
||||
let (text, nested, reference_text, reference_nested) = if reference_first {
|
||||
let reference_text = build_text(&values);
|
||||
let reference_nested = build_nested(&values);
|
||||
(GENERATED_BUILD_TEXT(&values).unwrap(), GENERATED_BUILD_NESTED(&values).unwrap(), reference_text, reference_nested)
|
||||
} else {
|
||||
(GENERATED_BUILD_TEXT(&values).unwrap(), GENERATED_BUILD_NESTED(&values).unwrap(), build_text(&values), build_nested(&values))
|
||||
};
|
||||
let maps = [Borrowed { text, nested, reference_text, reference_nested }];
|
||||
selection_comparisons(size);
|
||||
compare(
|
||||
&format!("map_text_owned_{size}"),
|
||||
&values,
|
||||
200,
|
||||
GENERATED_OWNED_TEXT,
|
||||
owned_text,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
&format!("map_text_borrowed_{size}"),
|
||||
&maps,
|
||||
200,
|
||||
borrowed_text,
|
||||
reference_borrowed_text,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
&format!("map_text_same_faults_{size}"),
|
||||
&maps,
|
||||
200,
|
||||
borrowed_text,
|
||||
reference_text_same_faults::<false>,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
&format!("map_text_same_table_{size}"),
|
||||
&maps,
|
||||
200,
|
||||
borrowed_text,
|
||||
reference_text_same_faults::<true>,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
&format!("map_nested_owned_{size}"),
|
||||
&values,
|
||||
200,
|
||||
GENERATED_OWNED_NESTED,
|
||||
owned_nested,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
&format!("map_nested_borrowed_{size}"),
|
||||
&maps,
|
||||
200,
|
||||
borrowed_nested,
|
||||
reference_borrowed_nested,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
&format!("list_first_owned_{size}"),
|
||||
&values,
|
||||
2000,
|
||||
list_first,
|
||||
reference_owned_text,
|
||||
|value| value.as_ref().map_or(0, |text| text.len() as u64),
|
||||
);
|
||||
compare(
|
||||
&format!("map_get_owned_{size}"),
|
||||
&values,
|
||||
2000,
|
||||
map_get,
|
||||
reference_owned_text,
|
||||
|value| value.as_ref().map_or(0, |text| text.len() as u64),
|
||||
);
|
||||
compare(
|
||||
&format!("map_nested_same_order_{size}"),
|
||||
&maps,
|
||||
200,
|
||||
borrowed_nested,
|
||||
reference_nested_same_order,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
&format!("map_nested_same_faults_{size}"),
|
||||
&maps,
|
||||
200,
|
||||
borrowed_nested,
|
||||
reference_nested_same_faults::<false>,
|
||||
|value| *value as u64,
|
||||
);
|
||||
compare(
|
||||
&format!("map_nested_same_table_{size}"),
|
||||
&maps,
|
||||
200,
|
||||
borrowed_nested,
|
||||
reference_nested_same_faults::<true>,
|
||||
|value| *value as u64,
|
||||
);
|
||||
let mut corpus: Vec<_> = (0..4)
|
||||
.map(|offset| {
|
||||
let mut input = values.clone();
|
||||
input.rotate_left(offset * 13);
|
||||
Borrowed {
|
||||
text: Map::with_capacity(0),
|
||||
nested: GENERATED_BUILD_NESTED(&input).unwrap(),
|
||||
reference_text: IndexMap::new(),
|
||||
reference_nested: IndexMap::new(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
for reverse in [false, true] {
|
||||
if reverse { corpus.reverse(); }
|
||||
compare(
|
||||
&format!("map_nested_corpus_{size}_{}", if reverse { "reverse" } else { "forward" }),
|
||||
&corpus,
|
||||
50,
|
||||
nested_corpus::<true>,
|
||||
nested_corpus::<false>,
|
||||
|value| *value as u64,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
// 独立 Rust 直接遍历 IndexMap;只复制命中项,保持结果顺序和拥有值语义。
|
||||
struct Selection {
|
||||
generated: Map<String, String>,
|
||||
reference: IndexMap<String, String>,
|
||||
target: String,
|
||||
}
|
||||
|
||||
fn selected_generated(input: &Selection) -> Result<Vec<(String, String)>, Fault> {
|
||||
GENERATED_MAP_FILTER(&input.generated, &input.target)
|
||||
}
|
||||
|
||||
fn selected_reference(input: &Selection) -> Result<Vec<(String, String)>, Fault> {
|
||||
let mut output = Vec::new();
|
||||
for (key, value) in &input.reference {
|
||||
if *value == input.target {
|
||||
output.push((key.clone(), value.clone()));
|
||||
}
|
||||
}
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
fn found_generated(input: &Selection) -> Result<Option<(String, String)>, Fault> {
|
||||
GENERATED_MAP_FIND(&input.generated, &input.target)
|
||||
}
|
||||
|
||||
fn found_reference(input: &Selection) -> Result<Option<(String, String)>, Fault> {
|
||||
for (key, value) in &input.reference {
|
||||
if *value == input.target {
|
||||
return Ok(Some((key.clone(), value.clone())));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
// 使用相同物理表与参数类型,单独检查生成层;独立 IndexMap 参照仍保留。
|
||||
fn selected_same_table(input: &Selection) -> Result<Vec<(String, String)>, Fault> {
|
||||
let mut output = Vec::new();
|
||||
let target = input.target.as_str();
|
||||
for (key, value) in input.generated.iter() {
|
||||
if value == target {
|
||||
output.push((key.clone(), value.clone()));
|
||||
}
|
||||
}
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
fn found_same_table(input: &Selection) -> Result<Option<(String, String)>, Fault> {
|
||||
let target = input.target.as_str();
|
||||
for (key, value) in input.generated.iter() {
|
||||
if value == target {
|
||||
return Ok(Some((key.clone(), value.clone())));
|
||||
}
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn selection_comparisons(size: usize) {
|
||||
let reference_first = std::env::var_os("DEVER_MAP_REFERENCE_FIRST").is_some();
|
||||
for mode in ["last", "first", "missing", "all"] {
|
||||
let suffix = "雪".repeat(size / 3);
|
||||
let target = format!(
|
||||
"{}:{suffix}",
|
||||
match mode {
|
||||
"last" => 63,
|
||||
"missing" => 64,
|
||||
_ => 0,
|
||||
}
|
||||
);
|
||||
let (mut generated, mut reference) = if reference_first {
|
||||
let reference = IndexMap::with_capacity(64);
|
||||
(Map::with_capacity(64), reference)
|
||||
} else {
|
||||
(Map::with_capacity(64), IndexMap::with_capacity(64))
|
||||
};
|
||||
for index in 0..64 {
|
||||
let key = format!("{index}:{suffix}");
|
||||
let value = if mode == "all" {
|
||||
target.clone()
|
||||
} else {
|
||||
key.clone()
|
||||
};
|
||||
if reference_first {
|
||||
reference.insert(key.clone(), value.clone());
|
||||
generated.insert(key, value);
|
||||
} else {
|
||||
generated.insert(key.clone(), value.clone());
|
||||
reference.insert(key, value);
|
||||
}
|
||||
}
|
||||
let values = Selection {
|
||||
generated,
|
||||
reference,
|
||||
target,
|
||||
};
|
||||
// 直接传入表和目标,空表断言复用同一入口,不额外包单元素数组。
|
||||
let empty = Selection {
|
||||
generated: Map::with_capacity(0),
|
||||
reference: IndexMap::new(),
|
||||
target: String::new(),
|
||||
};
|
||||
if mode != "first" {
|
||||
for (suffix, reference) in [
|
||||
("", selected_reference as fn(&Selection) -> _),
|
||||
("_same_table", selected_same_table as fn(&Selection) -> _),
|
||||
] {
|
||||
compare_output::<false, _, _>(
|
||||
&format!("map_filter_{mode}_{size}{suffix}"),
|
||||
&values,
|
||||
&empty,
|
||||
500,
|
||||
selected_generated,
|
||||
reference,
|
||||
|entries| {
|
||||
entries
|
||||
.iter()
|
||||
.map(|(key, value)| (key.len() + value.len()) as u64)
|
||||
.sum()
|
||||
},
|
||||
"rust",
|
||||
);
|
||||
}
|
||||
}
|
||||
if mode != "all" {
|
||||
for (suffix, reference) in [
|
||||
("", found_reference as fn(&Selection) -> _),
|
||||
("_same_table", found_same_table as fn(&Selection) -> _),
|
||||
] {
|
||||
compare_output::<false, _, _>(
|
||||
&format!("map_find_{mode}_{size}{suffix}"),
|
||||
&values,
|
||||
&empty,
|
||||
500,
|
||||
found_generated,
|
||||
reference,
|
||||
|entry| {
|
||||
entry
|
||||
.as_ref()
|
||||
.map_or(0, |(key, value)| (key.len() + value.len()) as u64)
|
||||
},
|
||||
"rust",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user