When debugging performance in Vega apps, the KPI Visualizer generates two types of trace data: Perfetto traces (system-level CPU, GPU, frame timing) and JS Profiler traces (JavaScript function-level execution). By default these are separate files, but merging them lets you see exactly which JS functions were running during frame drops or input delays. This guide walks through how to combine them for side-by-side analysis in Perfetto UI.
The JS Profiler trace and Perfetto trace files are located in a session-specific subdirectory (e.g. 2024-11-13_15-27-56) under the output/ directory of your app project. The exact path may vary depending on your tooling version — older versions used a generated/ directory.
Perfetto trace files follow the naming convention iter_*_vs_trace, while JS profiler trace files follow iter_*_trace*-original.json.
Follow the steps below to merge the JS function traces into a Perfetto trace file so you can analyze them alongside each other in Perfetto UI.
Convert Perfetto trace file to JSON
- Go to https://ui.perfetto.dev/ and open the Perfetto binary file
iter_*_vs_trace, then click “Convert to .json” in the left-hand pane.
This will download a file called trace.json to your Downloads directory. Rename this file to iter_*_vs_trace.json to match the naming convention of the Perfetto binary file.
Merge JS Profiler trace file into Perfetto trace file
- Open the JS Profiler trace file
iter_*_trace*-original.jsonin a text editor. It contains a JSON array of trace event objects. Copy all the objects inside the array (without the outer[and]delimiters). For example, the file will look like this:
[
{
"ts": 10281056953,
"pid": 2,
"tid": 29,
"ph": "B",
"name": "[root]",
"cat": "root",
"args": {
"name": "[root]",
"category": "root",
"url": null,
"line": null,
"column": null,
"params": null,
"allocatedCategory": "root",
"allocatedName": "[root]"
}
},
...
]
Copy everything between (but not including) the outer [ and ].
-
Open the Perfetto trace JSON file
iter_*_vs_trace.jsoncreated in step [1]. -
Paste the JS profiler trace events at the beginning of the
"traceEvents"array in the Perfetto trace JSON file. Make sure to add a comma after the last pasted object to maintain valid JSON array syntax. The result should look like this:
{"traceEvents":[
{"ts":10281056953,"pid":2,"tid":29,"ph":"B","name":"[root]","cat":"root","args":{}},
...
{"args":{"name":"foo"},"cat":"bar","name":"thread_name","ph":"M","pid":0,"tid":0,"ts":0}
]}
Note: The
pidin the JS profiler trace file doesn’t align with thepidin the Perfetto trace file. This can lead to incorrect process names being shown for JS profiler track events in Perfetto UI. To avoid confusion, replace thepidvalues in the JS profiler trace events with the PID of your app process (found in the Perfetto traces).
-
Save the file as
iter_*_combined-js-profiler-perfetto-traces.json. -
Open the merged file in ui.perfetto.dev to analyze JS profiler output alongside Perfetto traces.
-
Search for
[root]in the Perfetto search bar to find the JS profiler traces swimlane.
Related resources
- Inspect Traces in Vega Apps
- Investigate JavaScript Thread Performance
- Measure App KPIs
- Perfetto UI
- Vega App Performance Series, Part 2: Investigate Performance Issues
Last updated: Mar 11, 2026

