perf(html): escape_html 链式 5 次 replace 改单遍扫描
旧实现链式 5 次 str::replace,每次全量扫描 + 分配新 String, 5 个特殊字符 = 5 次堆分配 + 5 遍全文扫描,中间 4 个 String 立即丢弃。 新实现:先按字节快速检测是否含特殊字符(纯文本直接 clone 返回), 否则单遍 match 扫描 + 单次 with_capacity 分配。 分配 5→1(-80%),扫描 5→1。该函数被 markdown 渲染管线密集调用 (每个标题文本、每个 runnable 代码块的 overrides/source 转义)。
This commit is contained in:
parent
604febde98
commit
b34f44d3e7
@ -9,13 +9,30 @@
|
||||
///
|
||||
/// 单引号统一为 `'`(HTML5 规范,与原 server 端 `helpers::escape_html` 一致)。
|
||||
/// 可安全用于文本节点与属性值上下文。
|
||||
///
|
||||
/// 单遍扫描:旧实现链式调用 5 次 `str::replace`,每次全量扫描 + 分配一个新 String,
|
||||
/// 5 个特殊字符意味着 5 次堆分配 + 5 遍扫描。单遍 `match` 只扫描一次、只分配一次。
|
||||
/// 该函数被 markdown 渲染管线密集调用(每个标题、每个代码块),属于热点路径。
|
||||
pub fn escape_html(input: &str) -> String {
|
||||
input
|
||||
.replace('&', "&")
|
||||
.replace('<', "<")
|
||||
.replace('>', ">")
|
||||
.replace('"', """)
|
||||
.replace('\'', "'")
|
||||
// 快速路径:无特殊字符直接 clone(大多纯文本走这里,零额外扫描)。
|
||||
// memchr 风格的逐字节查找比总是分配 + 遍历更省。
|
||||
if !input.as_bytes().iter().any(|&b| {
|
||||
matches!(b, b'&' | b'<' | b'>' | b'"' | b'\'')
|
||||
}) {
|
||||
return input.to_string();
|
||||
}
|
||||
let mut out = String::with_capacity(input.len());
|
||||
for c in input.chars() {
|
||||
match c {
|
||||
'&' => out.push_str("&"),
|
||||
'<' => out.push_str("<"),
|
||||
'>' => out.push_str(">"),
|
||||
'"' => out.push_str("""),
|
||||
'\'' => out.push_str("'"),
|
||||
_ => out.push(c),
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user