分析
🌐 Profiling
在发布模式下编译 oxlint 并包含调试信息
🌐 Compiling oxlint in release mode with debug information
进行性能分析时,你需要在启用调试信息的情况下以发布模式编译 oxlint 二进制文件。你可以通过将 --profile release-with-debug 传递给 cargo build 来实现:
🌐 For profiling, you will need to compile the oxlint binary in release mode with debug information enabled. You can do that by passing --profile release-with-debug to cargo build:
cargo build --profile release-with-debug --bin oxlint构建完成后,二进制文件位于 ./target/release-with-debug/oxlint。这是应该用于性能分析的二进制文件。
🌐 After building, the binary is located at ./target/release-with-debug/oxlint. This is the binary that should be used for profiling.
CPU - Samply
Samply 是一个命令行 CPU 分析器,它使用 Firefox 分析器作为其用户界面。适用于 macOS 和 Linux。
要在 oxlint 上使用 Samply,请先运行 samply record,然后运行 oxlint 命令及其参数:
🌐 To use Samply with oxlint, run samply record followed by the oxlint command and arguments:
samply record ./target/release-with-debug/oxlint .为了改善分析体验,你可以考虑以下一些选项:
🌐 To improve the profiling experience, you might consider some of the following options:
oxlint:--silent将抑制诊断输出,使配置文件更专注。oxlint:--threads 1将以单线程模式运行代码检查器,这会更慢,但可以更容易地分析单线程性能的分析结果。samply record:--rate <number>将以更高的频率采样配置文件。默认值为1000Hz(1毫秒),但增加采样频率会提供更详细的信息,但配置文件文件会变大。
例如,单线程运行采样率为0.1毫秒的“oxlint”:
🌐 For example, running oxlint single-threaded with a 0.1ms sample rate:
samply record --rate 10000 ./target/release-with-debug/oxlint --silent --threads 1 .CPU - Mac Xcode 工具
🌐 CPU - Mac Xcode Instruments
cargo instruments 是连接 Mac Xcode 工具的首选工具。
以下指令复制了 cargo instruments 的操作步骤。
🌐 The following instruction replicates the procedure of cargo instruments.
首先,安装 Xcode Instruments 命令行工具:
🌐 First, install Xcode Instruments command-line tools:
xcode-select --install然后,如果你还没有这样做,确保 oxlint 二进制文件已被编译。
🌐 Then, if you haven't already, ensure that the oxlint binary is compiled.
在底层,cargo instruments 调用了 xcrun xctrace 命令,这等同于
🌐 Under the hood, cargo instruments invokes the xcrun xctrace command, which is equivalent to
xcrun xctrace record --template 'Time Profile' --output . --launch -- /path/to/oxc/target/release-with-debug/oxlint运行上述命令会产生以下输出
🌐 Running the command above produces the following output
Starting recording with the Time Profiler template. Launching process: oxlint.
Ctrl-C to stop the recording
Target app exited, ending recording...
Recording completed. Saving output file...
Output file saved as: Launch_oxlint_2023-09-03_4.41.45 PM_EB179B85.trace打开跟踪文件 open Launch_oxlint_2023-09-03_4.41.45\ PM_EB179B85.trace。
🌐 Open the trace file open Launch_oxlint_2023-09-03_4.41.45\ PM_EB179B85.trace.
要查看自上而下的跟踪:
🌐 To see a top down trace:
- 在顶部面板上,点击 CPU
- 在左侧输入框中,点击
x然后选择Time Profiler - 在底部面板,点击“调用树”,打开“反转调用树”,并关闭按线程分开。
对于内存和磁盘操作,使用 --template 'Allocations' 和 --template 'File Activity'。
🌐 For memory and disk operations, use --template 'Allocations' and --template 'File Activity'.
要进行更详细的 CPU 分析,例如 L1/L2 缓存未命中、周期和指令计数,以及分支预测信息,你需要使用自定义的“CPU 计数器”模板:
🌐 For more detailed CPU profiling, such as L1/L2 cache misses, cycle and instruction counts, and branch prediction info, you need to use a custom "CPU Counters" template:
- 打开 Instruments 并选择“CPU 计数器”模板。
- 在“CPU 计数器”设置中:
- 打开“高频采样”选项。
- 在“高频采样”选项下,点击加号图标并选择事件类型。一些建议的事件类型:
- Cycles - 用于大致了解每个函数消耗了多少 CPU 周期。
- 说明 - 用于大致了解每个函数执行了多少 CPU 指令以及花费了多少周期
L1D_CACHE_MISS_LD- 从内存加载数据时 L1 缓存未命中的次数
- 一旦你启用了感兴趣的事件,请在“文件 > 另存为模板...”中保存模板,并为其命名。
- 现在你可以通过将模板名称传递给
--template选项来在xctrace中使用它:xcrun xctrace record --template 'My Custom CPU Counters' --output . --launch -- /path/to/oxc/target/release-with-debug/oxlint
堆分配 - dhat
🌐 Heap Allocation - dhat
dhat 是一个堆分析器,可以帮助识别内存泄漏并分析堆分配模式。
安装
🌐 Setup
将 dhat 添加为你的 Cargo.toml 的依赖:
🌐 Add dhat as a dependency to your Cargo.toml:
[dependencies]
dhat = "0.3"然后在你的二进制 crate 顶部添加一个全局分配器:
🌐 Then add a global allocator at the top of your binary crate:
#[global_allocator]
static ALLOC: dhat::Alloc = dhat::Alloc;分析
🌐 Profiling
在你想要分析的范围内创建一个分析器。该分析器将跟踪从创建到被销毁期间的分配情况:
🌐 Create a profiler in the scope you want to profile. The profiler will track allocations from when it's created until it's dropped:
fn main() {
let _profiler = dhat::Profiler::new_heap();
// Your code here - all heap allocations will be tracked
}你也可以将 _profiler 添加到任何函数,以仅跟踪该特定函数的内存使用情况:
🌐 You can also add _profiler to any function to track memory only for that specific function:
fn my_function() {
let _profiler = dhat::Profiler::new_heap();
// Only allocations within this function scope will be tracked
}当分析器被丢弃时,它会自动生成一个 dhat-heap.json 文件。
🌐 The profiler will automatically generate a dhat-heap.json file when it's dropped.
加载和读取配置文件
🌐 Loading and Reading the Profile
运行程序后,你的工作目录中会创建一个 dhat-heap.json 文件。
🌐 After running your program, a dhat-heap.json file will be created in your working directory.
要分析资料:
🌐 To analyze the profile:
- 在 https://nnethercote.github.io/dh_view/dh_view.html 打开 dhat 查看器
- 加载
dhat-heap.json文件 - 在“排序指标”中选择一个指标以分析内存使用的不同方面:
- “在 t-gmax 时(字节)”:显示在内存使用峰值时的分配情况。使用此信息可识别在程序达到最大堆大小时,哪些部分占用了最多内存。
- “t-end(字节)”:显示在分析器销毁之前未释放的内存。这对于识别内存泄漏特别有用,因为它显示了在分析范围结束时仍然存在的分配。
- “总计(字节)”:显示整个执行过程中分配的字节总数。使用此信息可以识别代码中哪些部分分配了最多的内存,即使这些内存在之后被释放。
高级:控制分析器的生命周期
🌐 Advanced: Controlling Profiler Lifetime
为了更好地控制性能分析的停止时间,你可以显式地管理分析器的生命周期。例如,只分析核心逻辑而排除清理部分:
🌐 For more control over when profiling stops, you can explicitly manage the profiler's lifetime. For example, to profile only the core logic and exclude cleanup:
struct MyApp {
profiler: Option<dhat::Profiler>,
// other fields
}
impl MyApp {
fn close(&mut self) {
// Drop the profiler here to capture the heap state before cleanup
self.profiler = None;
// cleanup code
}
}这个模式有助于识别在程序执行的特定时刻哪些数据结构占用了内存。
🌐 This pattern helps identify which data structures are holding memory at a specific point in your program's execution.
