perf: 字符串 +/+= 二元拼接改 Cons rope 惰性扁平化消除 O(n²)
JsString 拆 Flat/Cons 变体:Cons 经独立 ConsNode 保存左右子节点 + O(1) 字节长 + 惰性扁平化产物缓存(OnceLock 原子发布,产物挂节点生命周期)。 concat_strings 接线:总长 ≤ 128B 的小链急切扁平(与 rope 前同款,拼接即 消费场景零开销),大链 O(1) 链接——大段重复拼接从 O(n²) 拷贝降为 O(n) 链接,文本在消费点(.length/==/string_ref/方法族)首次扁平化后缓存。 GC 兼容:mark 收口 mark_string_live 传播 Cons 子节点与产物闭包(显式栈 防深链爆栈);sweep/full_reset 共用 drop 辅助连带释放产物;节点字节记账 用 O(1) byte_len。rope 节点登记 session 字符串表,与执行期字符串 GC (指令边界触发)天然兼容。JsString 结构 32B 与 rope 前同 bin,小串路径 零结构回退;unsafe impl Send/Sync 论证同 StringPtr(perm 恒 Flat)。
This commit is contained in:
@@ -175,6 +175,33 @@ pub fn single_char_ptr(ch: u8) -> *const JsString {
|
||||
}
|
||||
}
|
||||
|
||||
/// 小整数(0..=99)永久 `JsString` 指针表:`s += j` 等数字叶子拼接的高频命中路径,
|
||||
/// 免每次 `to_string` + 登记 2 次分配。泄漏面严格有界:100 条目 ≈ 4KB,进程生命
|
||||
/// 期内不释放(同 `SINGLE_CHAR_TABLE` 论证)。
|
||||
static SMALL_INT_TABLE: [OnceLock<StringPtr>; 100] = [const { OnceLock::new() }; 100];
|
||||
|
||||
/// 取 0..=99 小整数的永久 `JsString` 指针,惰性物化一次后恒返回同一地址。
|
||||
/// 超出范围返回 `None`,由调用方回落普通字符串创建。
|
||||
pub fn small_int_ptr(n: u32) -> Option<*const JsString> {
|
||||
if n >= 100 {
|
||||
return None;
|
||||
}
|
||||
let slot = &SMALL_INT_TABLE[n as usize];
|
||||
if let Some(ptr) = slot.get() {
|
||||
return Some(ptr.0);
|
||||
}
|
||||
let ptr = Box::into_raw(Box::new(JsString::new(n.to_string())));
|
||||
match slot.set(StringPtr(ptr)) {
|
||||
Ok(()) => Some(ptr),
|
||||
Err(existing) => {
|
||||
// 并发首用竞态:与 single_char_ptr 同款处置,本线程产物恰好释放一次。
|
||||
// SAFETY: ptr 来自本线程的 Box::into_raw,无任何外部引用。
|
||||
unsafe { drop(Box::from_raw(ptr)) };
|
||||
Some(existing.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
Reference in New Issue
Block a user