fn chain_reference(values: &[String]) -> Result { let value = values.first().map(String::as_str).unwrap_or(""); let mut output = String::with_capacity(value.len() + value.len() + 3); output.push('['); output.push_str(value); output.push(':'); output.push_str(value); output.push(']'); Ok(output) } fn chain_generated(values: &[String]) -> Result { GENERATED_CHAIN(values.first().map(String::as_str).unwrap_or("")) } // 与 Dever 的 str 函数边界一致;原切片入口参照仍保留。 fn chain_native(value: &str) -> Result { let mut output = String::with_capacity(value.len() + value.len() + 3); output.push('['); output.push_str(value); output.push(':'); output.push_str(value); output.push(']'); Ok(output) } fn chain_boundary(values: &[String]) -> Result { chain_native(values.first().map(String::as_str).unwrap_or("")) } fn pair_reference(values: &[String]) -> Result { let value = values.first().map(String::as_str).unwrap_or(""); let mut output = String::with_capacity(value.len() + value.len()); output.push_str(value); output.push_str(value); Ok(output) } fn pair_generated(values: &[String]) -> Result { GENERATED_PAIR(values.first().map(String::as_str).unwrap_or("")) } fn temporary_generated(values: &[String]) -> Result { GENERATED_TEMPORARY(values.first().map(String::as_str).unwrap_or("")) } fn temporary_reference(values: &[String]) -> Result { let value = values.first().map(String::as_str).unwrap_or(""); let mut output = String::with_capacity(value.len() + "后".len()); output.push_str(value); output.push_str("后"); Ok(output) } fn forwarded_generated(values: &[String]) -> Result { GENERATED_FORWARDED(values.first().map(String::as_str).unwrap_or("")) } fn contains_reference(values: &[SEARCH_PAIR]) -> Result { let mut total = 0i64; for pair in values { total = total .checked_add(if pair.field0.contains(pair.field1.as_str()) { 120 } else { 0 }) .ok_or( const { &FaultInfo { message: "integer arithmetic fault", source: "reference", line: 1, column: 1, } }, )?; } Ok(total) } fn concatenate_text_reference(values: &[String]) -> Result { let mut output = String::new(); for value in values { output.push_str(value); } Ok(output) } fn concatenate_bytes_reference( values: &[dever_runtime::Bytes], ) -> Result { let mut output = Vec::new(); for value in values { output.extend_from_slice(value); } Ok(output.into()) } fn main() { println!("case,sample,implementation,elapsed_ns,checksum"); for count in [8, 256, 4096] { let values = vec!["雪山".to_owned(); count]; compare( &format!("list_contains_{count}"), &values, 2000, list_contains_generated, list_contains_reference, |found| u64::from(*found), ); } // 双方使用同一批 String;独立 Rust 实现只调用标准库,排除分配布局和内置时钟差异。 for count in [512, 1024, 2048, 4096] { let values: Vec<_> = (0..count) .map(|_| { let text = "compare-value-120".to_owned(); let pattern = text.to_uppercase().to_lowercase(); SEARCH_PAIR { field0: text, field1: pattern, } }) .collect(); compare( &format!("text_contains_{count}"), &values, 1000, GENERATED_CONTAINS, contains_reference, |value| *value as u64, ); } let values: Vec<_> = [ ("雪山🙂", "山"), ("abc", "z"), ("abc", ""), ("", "x"), ("", ""), ] .into_iter() .map(|(text, pattern)| SEARCH_PAIR { field0: text.into(), field1: pattern.into(), }) .collect(); assert_eq!(GENERATED_CONTAINS(&values).unwrap(), 360); assert_eq!(contains_reference(&values).unwrap(), 360); for count in [512, 2048, 8192, 32768] { let texts = vec!["x".to_owned(); count]; let bytes = (0..count) .map(|_| dever_runtime::Bytes::from(vec![b'x'])) .collect::>(); compare( &format!("text_concat_{count}"), &texts, 200, GENERATED_TEXT_CONCAT, concatenate_text_reference, |value| value.len() as u64, ); compare( &format!("bytes_concat_{count}"), &bytes, 200, GENERATED_BYTES_CONCAT, concatenate_bytes_reference, |value| value.len() as u64, ); } for (name, value, count) in [ ("text_chain_empty", String::new(), 300000), ("text_chain_small", "雪山".repeat(2), 300000), ("text_chain_large", "雪山".repeat(1024), 30000), ] { let values = [value]; compare( name, &values, count, chain_generated, chain_reference, |value| value.len() as u64, ); compare( &format!("{name}_boundary"), &values, count, chain_generated, chain_boundary, |value| value.len() as u64, ); compare_borrowed( name, &values, count, chain_generated, chain_reference, |value| value.len() as u64, ); } compare( "text_pair", &["雪山".repeat(32)], 300000, pair_generated, pair_reference, |value| value.len() as u64, ); for (name, value, count) in [ ("text_temporary_empty", String::new(), 300000), ("text_temporary_small", "雪山".repeat(2), 300000), ("text_temporary_medium", "雪山".repeat(32), 300000), ("text_temporary_large", "雪山".repeat(1024), 30000), ] { let values = [value]; compare( name, &values, count, temporary_generated, temporary_reference, |value| value.len() as u64, ); compare( &format!("{name}_forwarded"), &values, count, forwarded_generated, temporary_reference, |value| value.len() as u64, ); compare_borrowed( name, &values, count, temporary_generated, temporary_reference, |value| value.len() as u64, ); compare_borrowed( &format!("{name}_forwarded"), &values, count, forwarded_generated, temporary_reference, |value| value.len() as u64, ); } } fn list_contains_generated(values: &[String]) -> Result { GENERATED_LIST_CONTAINS(values, "absent") } fn list_contains_reference(values: &[String]) -> Result { Ok(values.iter().any(|item| item.as_str() == "absent")) }