perf: 字符串拼接按操作数字节长预分配容量,免几何 realloc 二次拷贝
This commit is contained in:
@@ -16,12 +16,16 @@ impl Vm {
|
|||||||
let lhs = self.coerce_primitive_bounded(lv, false)?;
|
let lhs = self.coerce_primitive_bounded(lv, false)?;
|
||||||
let rhs = self.coerce_primitive_bounded(rv, false)?;
|
let rhs = self.coerce_primitive_bounded(rv, false)?;
|
||||||
if lhs.is_string() || rhs.is_string() {
|
if lhs.is_string() || rhs.is_string() {
|
||||||
let mut buf = std::mem::take(&mut self.string_buf);
|
let lbytes = if lhs.is_string() { unsafe { (*lhs.as_string_ptr()).len() } } else { 0 };
|
||||||
buf.clear();
|
let rbytes = if rhs.is_string() { unsafe { (*rhs.as_string_ptr()).len() } } else { 0 };
|
||||||
|
// 预分配精确容量:字符串操作数 O(1) 取字节长,一次分配写齐,免 push_str
|
||||||
|
// 几何 realloc 的二次拷贝(字符串拼接热路径的主要额外成本)。
|
||||||
|
// 32 字节余量覆盖数字/布尔等格式化文本(f64 文本最长约 24 字节),
|
||||||
|
// 避免追加非字符串操作数时二次扩容。
|
||||||
|
let mut buf = String::with_capacity(lbytes + rbytes + 32);
|
||||||
coercion::push_to_string(lhs, &mut buf);
|
coercion::push_to_string(lhs, &mut buf);
|
||||||
coercion::push_to_string(rhs, &mut buf);
|
coercion::push_to_string(rhs, &mut buf);
|
||||||
let result = self.new_string_owned(buf);
|
let result = self.new_string_owned(buf);
|
||||||
self.string_buf = String::new();
|
|
||||||
self.regs[rd] = result;
|
self.regs[rd] = result;
|
||||||
} else {
|
} else {
|
||||||
let ln = coercion::to_number(lhs);
|
let ln = coercion::to_number(lhs);
|
||||||
@@ -58,12 +62,16 @@ impl Vm {
|
|||||||
let lhs = self.coerce_primitive_bounded(lv, false)?;
|
let lhs = self.coerce_primitive_bounded(lv, false)?;
|
||||||
let rhs = self.coerce_primitive_bounded(rv, false)?;
|
let rhs = self.coerce_primitive_bounded(rv, false)?;
|
||||||
if lhs.is_string() || rhs.is_string() {
|
if lhs.is_string() || rhs.is_string() {
|
||||||
let mut buf = std::mem::take(&mut self.string_buf);
|
let lbytes = if lhs.is_string() { unsafe { (*lhs.as_string_ptr()).len() } } else { 0 };
|
||||||
buf.clear();
|
let rbytes = if rhs.is_string() { unsafe { (*rhs.as_string_ptr()).len() } } else { 0 };
|
||||||
|
// 预分配精确容量:字符串操作数 O(1) 取字节长,一次分配写齐,免 push_str
|
||||||
|
// 几何 realloc 的二次拷贝(字符串拼接热路径的主要额外成本)。
|
||||||
|
// 32 字节余量覆盖数字/布尔等格式化文本(f64 文本最长约 24 字节),
|
||||||
|
// 避免追加非字符串操作数时二次扩容。
|
||||||
|
let mut buf = String::with_capacity(lbytes + rbytes + 32);
|
||||||
coercion::push_to_string(lhs, &mut buf);
|
coercion::push_to_string(lhs, &mut buf);
|
||||||
coercion::push_to_string(rhs, &mut buf);
|
coercion::push_to_string(rhs, &mut buf);
|
||||||
let result = self.new_string_owned(buf);
|
let result = self.new_string_owned(buf);
|
||||||
self.string_buf = String::new();
|
|
||||||
self.regs[rd] = result;
|
self.regs[rd] = result;
|
||||||
} else {
|
} else {
|
||||||
let ln = coercion::to_number(lhs);
|
let ln = coercion::to_number(lhs);
|
||||||
|
|||||||
@@ -348,8 +348,6 @@ pub struct Vm {
|
|||||||
/// 分组保存 inline cache 与指令计数器。
|
/// 分组保存 inline cache 与指令计数器。
|
||||||
pub(crate) profiling: ProfilingState,
|
pub(crate) profiling: ProfilingState,
|
||||||
pub(crate) cell_stack: Vec<Vec<*mut Cell>>,
|
pub(crate) cell_stack: Vec<Vec<*mut Cell>>,
|
||||||
/// 可复用字符串缓冲区,避免每次 `+` 拼接都分配。
|
|
||||||
pub(crate) string_buf: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vm {
|
impl Vm {
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ impl Vm {
|
|||||||
ic_misses: std::cell::Cell::new(0),
|
ic_misses: std::cell::Cell::new(0),
|
||||||
instruction_count: 0,
|
instruction_count: 0,
|
||||||
},
|
},
|
||||||
string_buf: String::new(),
|
|
||||||
cell_stack: Vec::new(),
|
cell_stack: Vec::new(),
|
||||||
};
|
};
|
||||||
vm.init_generator_intrinsics();
|
vm.init_generator_intrinsics();
|
||||||
@@ -190,7 +189,6 @@ impl Vm {
|
|||||||
ic_misses: std::cell::Cell::new(0),
|
ic_misses: std::cell::Cell::new(0),
|
||||||
instruction_count: 0,
|
instruction_count: 0,
|
||||||
},
|
},
|
||||||
string_buf: String::new(),
|
|
||||||
cell_stack: Vec::new(),
|
cell_stack: Vec::new(),
|
||||||
};
|
};
|
||||||
vm.init_generator_intrinsics();
|
vm.init_generator_intrinsics();
|
||||||
|
|||||||
Reference in New Issue
Block a user