Trace 支持你在代码中添加自定义 Trace 事件,帮助你追踪特定操作或业务流程。这对于分析自定义业务逻辑、统计耗时或标记应用中的关键节点非常有用。
通过添加自定义 Trace 事件,你可以将代码中不透明的部分转化为 Trace 时间线中可视且可度量的区间,从而实现精准的性能调优。
子事件必须始终在其父事件结束前结束(即 B 必须在 A 之前结束)
// 基础用法
- (void)measure {
[LynxTraceEvent beginSection:@"render" withName:@"measure"]; // 'measure' slice 开始
// ... 你的代码 ...
[LynxTraceEvent endSection:@"render" withName:@"measure"]; // 'measure' slice 结束
}
// 带自定义参数
- (void)draw {
[LynxTraceEvent beginSection:@"render" withName:@"draw-image" debugInfo:@{@"component": @"Image", @"size": @"large"}];
// ... 你的代码 ...
[LynxTraceEvent endSection:@"render" withName:@"draw-image"];
}
// 基础用法
- (void)requestBegin {
// ...
[LynxTraceEvent instant:@"network" withName:@"request-begin"];
// ...
}
// 带自定义参数
- (void)requestFinished {
// ...
[LynxTraceEvent instant:@"network" withName:@"request-finished" debugInfo:@{@"url": @"https://example.com", @"method": @"GET"}];
// ...
}
beginSection
必须有一个对应的 endSection
,且这两个调用必须发生在同一线程。endSection
未被调用。// 异常导致 endSection 未被调用
- (void)measureWithError:(BOOL)shouldThrow {
[LynxTraceEvent beginSection:@"measure"];
// ...
@throw [NSException exceptionWithName:@"TestException" reason:@"Error occurred" userInfo:nil];
// 异常导致 endSection 未被调用
[LynxTraceEvent endSection:@"measure"];
}
// 提前 return 导致 endSection 未被调用
- (void)measureWithFastExit:(BOOL)fastExit {
[LynxTraceEvent beginSection:@"measure"];
// 直接返回,endSection 未被调用
if (fastExit) return;
// ...
[LynxTraceEvent endSection:@"measure"];
}
// 跨线程调用导致 begin/end 不匹配
[LynxTraceEvent beginSection:@"background-task"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// ...
[LynxTraceEvent endSection:@"background-task"]; // 错误:不在同一线程
});
- (void)measureWithError:(BOOL)shouldThrow {
@try {
LynxTraceEvent beginSection:@"measure"];
// ...
@throw [NSException exceptionWithName:@"TestException" reason:@"Error occurred" userInfo:nil];
}
@finally {
// 异常安全,确保 endSection 一定被调用
[LynxTraceEvent endSection:@"measure"];
}
}
- (void)measureWithFastExit:(BOOL)fastExit {
[LynxTraceEvent beginSection:@"measure"];
if (fastExit) {
// 提前 return 安全示例
[LynxTraceEvent endSection:@"measure"];
return;
}
// ...
[LynxTraceEvent endSection:@"measure"];
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 线程安全示例:begin/end 在同一线程
[LynxTraceEvent beginSection:@"background-task"];
// ...
[LynxTraceEvent endSection:@"background-task"];
});
beginSection
/endSection
。// 定时器/回调
[LynxTraceEvent beginSection:@"async-function"];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, time), dispatch_get_main_queue(), ^{
// ...
[LynxTraceEvent endSection:@"async-function"];
});
// 异步任务
[LynxTraceEvent beginSection:@"await-task"];
[someAsyncFunction waitUntilFinished];
[LynxTraceEvent endSection:@"await-task"];
// 定时器/回调:在回调内部成对使用
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, time), dispatch_get_main_queue(), ^{
[LynxTraceEvent beginSection:@"async-function"];
// ...
[LynxTraceEvent endSection:@"async-function"];
});
// 异步任务:使用即时事件
[LynxTraceEvent instant:@"async-task" withName:@"start"];
[someAsyncFunction waitUntilFinished];
[LynxTraceEvent instant:@"async-task" withName:@"end"];
子事件必须始终在其父事件结束前结束(即 B 必须在 A 之前结束)
// 基础用法
void measure() {
TraceEvent.beginSection("render", "measure");
// ... 你的代码 ...
TraceEvent.endSection("render", "measure");
}
// 带自定义参数
void draw() {
Map<String, String> args = new HashMap<>();
args.put("component", "Image");
args.put("size", "large");
TraceEvent.beginSection("render", "draw-image", args);
// ... 你的代码 ...
TraceEvent.endSection("render", "draw-image");
}
// 基本用法
void requestBegin() {
// ...
TraceEvent.instant("network", "request-begin");
// ...
}
// 带自定义参数
void requestFinished() {
// ...
Map<String, String> args = new HashMap<>();
args.put("url", "https://example.com");
args.put("method", "GET");
TraceEvent.instant("network", "request-finished", args);
//...
}
beginSection
必须有一个对应的 endSection
,且这两个调用必须发生在同一线程。endSection
未被调用。public void measure() throws Exception {
TraceEvent.beginSection("measure");
// ...
exceptionFunction(); // 可能抛出异常
// 异常导致 endSection 未被调用
TraceEvent.endSection("measure");
}
public void measure(boolean fastExit) {
TraceEvent.beginSection("measure");
// 提前 return 导致 endSection 未被调用
if (fastExit) return;
// ...
TraceEvent.endSection("measure");
}
// 跨线程:begin/end 不在同一线程
TraceEvent.beginSection("background-task");
new Thread(() -> {
// ...
TraceEvent.endSection("background-task");
}).start();
public void measure() throws Exception {
try {
TraceEvent.beginSection("measure");
// ...
exceptionFunction();
} finally {
// 异常安全
TraceEvent.endSection("measure");
}
}
public void measure() {
TraceEvent.beginSection("measure");
if (fastExit) {
// 提前 return 安全
TraceEvent.endSection("measure");
return;
}
// ...
TraceEvent.endSection("measure");
}
new Thread(() -> {
// 线程安全:begin/end 在同一线程
TraceEvent.beginSection("background-task");
// ...
TraceEvent.endSection("background-task");
}).start();
beginSection
/endSection
。// 定时器/回调
TraceEvent.beginSection("async-function");
new Handler().postDelayed(() -> {
// ...
TraceEvent.endSection("async-function");
}, 3000);
// 异步任务
TraceEvent.beginSection("await-task");
someAsyncFunction().get(); // 假设这是异步等待
TraceEvent.endSection("await-task");
// 定时器/回调:在回调内部成对使用
new Handler().postDelayed(() -> {
TraceEvent.beginSection("async-function");
// ...
TraceEvent.endSection("async-function");
}, 3000);
// 异步任务:使用即时事件
TraceEvent.instant("async-task", "async-task-start");
someAsyncFunction().get();
TraceEvent.instant("async-task", "async-task-end");
子事件必须始终在其父事件结束前结束(即 B 必须在 A 之前结束)
// 基础用法
function handleClick() {
lynx.performance.profileStart('handle-click');
// ... 你的代码 ...
lynx.performance.profileEnd();
}
// 带自定义参数
useEffect(() => {
lynx.performance.profileStart('useEffect', {
args: { count },
});
// ... 你的代码 ...
lynx.performance.profileEnd();
}, [count]);
function fetchData() {
// 基础用法
lynx.performance.profileMark('fetch-data-begin');
fetch(url).then((res) => {
// 带自定义参数
lynx.performance.profileMark('fetch-data-end', {
args: { url: 'https://example.com', method: 'GET' },
});
});
}
const flowId = lynx.performance.profileFlowId();
lynx.performance.profileMark('user-action-begin', { flowId });
// ...稍后,在异步回调中
setTimeout(() => {
// ...
lynx.performance.profileMark('user-action-end', { flowId });
}, 1000);
profileStart
必须有一个对应的 profileEnd
,且这两个调用必须发生在同一线程。profileEnd
未被调用。function measure() {
lynx.performance.profileStart('measure');
// ...
throw new Error('Error occurred');
// 异常导致 profileEnd 未被调用
lynx.performance.profileEnd();
}
function measureWithFastExit(fastExit) {
lynx.performance.profileStart('measure');
// 直接返回,profileEnd 未被调用
if (fastExit) return;
// ...
lynx.performance.profileEnd();
}
// 跨异步线程调用导致 begin/end 不匹配
lynx.performance.profileStart('background-task');
setTimeout(() => {
// ...
lynx.performance.profileEnd();
}, 1000);
function measure(shouldThrow) {
try {
lynx.performance.profileStart('measure');
// ...
throw new Error('Error occurred');
} finally {
// 异常安全,确保 profileEnd 一定被调用
lynx.performance.profileEnd();
}
}
function measureWithFastExit(fastExit) {
lynx.performance.profileStart('measure');
if (fastExit) {
// 提前 return 安全示例
lynx.performance.profileEnd();
return;
}
// ...
lynx.performance.profileEnd();
}
setTimeout(() => {
// 线程安全示例:begin/end 在同一执行上下文
lynx.performance.profileStart('background-task');
// ...
lynx.performance.profileEnd();
}, 0);
await
/Promise
)之间使用 profileStart
/profileEnd
。// 定时器/回调
lynx.performance.profileStart('async function');
setTimeout(() => {
// ...
lynx.performance.profileEnd();
}, 3000);
// await/promise
lynx.performance.profileStart('await-task');
await someAsyncFunc();
lynx.performance.profileEnd();
// 定时器/回调:在回调内部成对使用
setTimeout(() => {
lynx.performance.profileStart('async function');
// ...
lynx.performance.profileEnd();
}, 3000);
// await/promise:使用 Instant 事件
lynx.performance.profileMark('async-task:start');
await someAsyncFunc();
lynx.performance.profileMark('async-task:end');