mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-26 11:41:13 +08:00
fix: 采样样本记表代际,直方图按代际解析函数名并订正并列注释
This commit is contained in:
@@ -235,12 +235,16 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 指令周期采样:开启时(周期为 2 的幂)每 period 条指令记一条样本
|
// 指令周期采样:开启时(周期为 2 的幂)每 period 条指令记一条样本
|
||||||
// (flat_id, pc, opcode, frames 深度),run 末聚合成 top-K 直方图;
|
// (flat_id, pc, opcode, frames 深度, 表代际),run 末聚合成 top-K
|
||||||
// 关闭时仅这一条可预测分支,零写零分配。
|
// 直方图;关闭时仅这一条可预测分支,零写零分配。
|
||||||
if self.sampling.period != 0 && (steps & (self.sampling.period - 1)) == 0 {
|
if self.sampling.period != 0 && (steps & (self.sampling.period - 1)) == 0 {
|
||||||
self.sampling
|
self.sampling.records.push((
|
||||||
.records
|
self.active_flat_id,
|
||||||
.push((self.active_flat_id, pc as u32, op as u8, self.frames.len() as u32));
|
pc as u32,
|
||||||
|
op as u8,
|
||||||
|
self.frames.len() as u32,
|
||||||
|
self.active_table_gen,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
|
|||||||
@@ -711,11 +711,11 @@ impl Vm {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 按 flat_id 聚合采样记录并向 stderr 输出 top-K 热点直方图。
|
/// 按 (flat_id, 表代际) 聚合采样记录并向 stderr 输出 top-K 热点直方图。
|
||||||
///
|
///
|
||||||
/// 聚合键取 (flat_id, pc):样本数按 flat_id 汇总,top pc 取该 flat_id 下
|
/// 聚合键取 (flat_id, 表代际, pc):样本数按 (flat_id, 表代际) 汇总,top pc
|
||||||
/// 样本数最多的字节码偏移(与反汇编 offset 列同单位)。函数名经当前表代际
|
/// 取该键下样本数最多的字节码偏移(与反汇编 offset 列同单位)。函数名经样本
|
||||||
/// 平表解析(顶层为 0),未知 flat_id 输出 `<flat N>`。
|
/// 记录表代际的平表解析(顶层为 0),未知 flat_id 输出 `<flat N>`。
|
||||||
///
|
///
|
||||||
/// # 边界
|
/// # 边界
|
||||||
/// - 采样关闭(`period == 0`)或无样本时直接返回,零输出零分配。
|
/// - 采样关闭(`period == 0`)或无样本时直接返回,零输出零分配。
|
||||||
@@ -724,23 +724,24 @@ impl Vm {
|
|||||||
if self.sampling.period == 0 || self.sampling.records.is_empty() {
|
if self.sampling.period == 0 || self.sampling.records.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 聚合:(flat_id, pc) → 样本数与 opcode;flat_id → 最大 frames 深度。
|
// 聚合:(flat_id, 表代际, pc) → 样本数与 opcode;
|
||||||
let mut pc_hist: HashMap<(u32, u32), (u64, u8)> = HashMap::new();
|
// (flat_id, 表代际) → 最大 frames 深度。
|
||||||
let mut flat_max_frames: HashMap<u32, u32> = HashMap::new();
|
let mut pc_hist: HashMap<(u32, u32, u32), (u64, u8)> = HashMap::new();
|
||||||
for &(flat, pc, op, frames) in &self.sampling.records {
|
let mut flat_max_frames: HashMap<(u32, u32), u32> = HashMap::new();
|
||||||
let entry = pc_hist.entry((flat, pc)).or_insert((0, op));
|
for &(flat, pc, op, frames, gen) in &self.sampling.records {
|
||||||
|
let entry = pc_hist.entry((flat, gen, pc)).or_insert((0, op));
|
||||||
entry.0 += 1;
|
entry.0 += 1;
|
||||||
let top = flat_max_frames.entry(flat).or_insert(frames);
|
let top = flat_max_frames.entry((flat, gen)).or_insert(frames);
|
||||||
if frames > *top {
|
if frames > *top {
|
||||||
*top = frames;
|
*top = frames;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 按 flat_id 汇总样本数,降序排列后取 top-K。
|
// 按 (flat_id, 表代际) 汇总样本数,降序排列后取 top-K。
|
||||||
let mut flat_total: HashMap<u32, u64> = HashMap::new();
|
let mut flat_total: HashMap<(u32, u32), u64> = HashMap::new();
|
||||||
for (&(flat, _), &(count, _)) in &pc_hist {
|
for (&(flat, gen, _), &(count, _)) in &pc_hist {
|
||||||
*flat_total.entry(flat).or_insert(0) += count;
|
*flat_total.entry((flat, gen)).or_insert(0) += count;
|
||||||
}
|
}
|
||||||
let mut ranked: Vec<(u32, u64)> = flat_total.into_iter().collect();
|
let mut ranked: Vec<((u32, u32), u64)> = flat_total.into_iter().collect();
|
||||||
ranked.sort_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
|
ranked.sort_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(&b.0)));
|
||||||
let k = self.sampling.top_k.min(ranked.len());
|
let k = self.sampling.top_k.min(ranked.len());
|
||||||
eprintln!(
|
eprintln!(
|
||||||
@@ -749,11 +750,12 @@ impl Vm {
|
|||||||
self.sampling.records.len(),
|
self.sampling.records.len(),
|
||||||
self.profiling.instruction_count
|
self.profiling.instruction_count
|
||||||
);
|
);
|
||||||
for (rank, &(flat, count)) in ranked.iter().take(k).enumerate() {
|
for (rank, &((flat, gen), count)) in ranked.iter().take(k).enumerate() {
|
||||||
// top pc:该 flat_id 下样本数最多的字节码偏移(并列取小 pc)。
|
// top pc:该 (flat_id, 表代际) 下样本数最多的字节码偏移(并列取哈希
|
||||||
|
// 遍历首个,非确定,诊断用途可接受)。
|
||||||
let mut top_pc: Option<(u64, u32, u8)> = None;
|
let mut top_pc: Option<(u64, u32, u8)> = None;
|
||||||
for (&(f, pc), &(c, op)) in &pc_hist {
|
for (&(f, g, pc), &(c, op)) in &pc_hist {
|
||||||
if f != flat {
|
if f != flat || g != gen {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
match top_pc {
|
match top_pc {
|
||||||
@@ -768,11 +770,11 @@ impl Vm {
|
|||||||
.unwrap_or_else(|_| format!("op{top_op}"));
|
.unwrap_or_else(|_| format!("op{top_op}"));
|
||||||
let name = self
|
let name = self
|
||||||
.tables
|
.tables
|
||||||
.get(&self.current_gen)
|
.get(&gen)
|
||||||
.and_then(|t| t.modules.get(flat as usize))
|
.and_then(|t| t.modules.get(flat as usize))
|
||||||
.and_then(|m| m.function_name.clone())
|
.and_then(|m| m.function_name.clone())
|
||||||
.unwrap_or_else(|| format!("<flat {flat}>"));
|
.unwrap_or_else(|| format!("<flat {flat}>"));
|
||||||
let frames = flat_max_frames.get(&flat).copied().unwrap_or(0);
|
let frames = flat_max_frames.get(&(flat, gen)).copied().unwrap_or(0);
|
||||||
eprintln!(
|
eprintln!(
|
||||||
" {rank:>2}. {name:<24} (flat {flat}) {count:>8} samples top pc={top_pc} {op_name} ({top_count}) frames={frames}"
|
" {rank:>2}. {name:<24} (flat {flat}) {count:>8} samples top pc={top_pc} {op_name} ({top_count}) frames={frames}"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -249,15 +249,15 @@ impl IterState {
|
|||||||
/// 指令周期采样状态:采样周期(2 的幂)与样本记录表。
|
/// 指令周期采样状态:采样周期(2 的幂)与样本记录表。
|
||||||
///
|
///
|
||||||
/// 开启时 dispatch 主循环每 `period` 条指令记一条样本(flat_id、pc、opcode、
|
/// 开启时 dispatch 主循环每 `period` 条指令记一条样本(flat_id、pc、opcode、
|
||||||
/// frames 深度),run 末按 flat_id 聚合并输出 top-K 直方图(stderr)。
|
/// frames 深度、表代际),run 末按 (flat_id, 表代际) 聚合并输出 top-K 直方图
|
||||||
/// 关闭(`period == 0`)时热路径仅一次可预测分支,零写零分配。
|
/// (stderr)。关闭(`period == 0`)时热路径仅一次可预测分支,零写零分配。
|
||||||
pub(crate) struct SampleState {
|
pub(crate) struct SampleState {
|
||||||
/// 采样周期(2 的幂,0 = 关闭)。
|
/// 采样周期(2 的幂,0 = 关闭)。
|
||||||
pub(crate) period: u64,
|
pub(crate) period: u64,
|
||||||
/// 直方图 top-K 大小(默认 10)。
|
/// 直方图 top-K 大小(默认 10)。
|
||||||
pub(crate) top_k: usize,
|
pub(crate) top_k: usize,
|
||||||
/// 样本记录:(flat_id, pc, opcode, frames 深度),run 边界清空。
|
/// 样本记录:(flat_id, pc, opcode, frames 深度, 表代际),run 边界清空。
|
||||||
pub(crate) records: Vec<(u32, u32, u8, u32)>,
|
pub(crate) records: Vec<(u32, u32, u8, u32, u32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SampleState {
|
impl SampleState {
|
||||||
|
|||||||
Reference in New Issue
Block a user