react-native-community / hermes-profile-transformer Goto Github PK
View Code? Open in Web Editor NEWTypeScript tool for converting Hermes Sampling Profiler output to Chrome Dev Tools format
License: MIT License
TypeScript tool for converting Hermes Sampling Profiler output to Chrome Dev Tools format
License: MIT License
The Trace Event Format has listed down the various chrome events and how they are understood by the Chrome Profiler.
The Chrome Profiler consumes this profiling data in the JSON Array Format while the Hermes Profile is generated in the JSON Object Format. We might have made an oversight in assuming that the traceEvents generated by the Hermes Profiler are going to have phases assigned similar to Chrome Profiler, however this is not the case.
The phases in the case of the Hermes Profile need to be derived from the Samples and Stack Frames Properties in the Hermes Profile. This is where things are accumulated from lower level OS Kernels and we need to make sense of this data.
I tried it out with my React Native app running on React Native 0.63.1 with Hermes enabled, but when I load the trace in Chrome Dev Tools, every item in the view is labeled as "anonymous". There are some details that list file names and line numbers specifically in the flame chart, and while the file names look like they could be correct, the line numbers make no sense when I look at the source. Additionally, the timing information doesn't make sense, as there are root level blocks in the flame graph that say they took ~250ms which is not possible as I'm using requestAnimationFrame
to render graphics at 60fps.
Since it seems like it isn't really working, my question is whether there is a min version of React Native (or Hermes specifically) supported by hermes-profile-transformer. Should it work for the version of Hermes included in React Native 0.63.1?
The migration of Duration events to Complete events would be extremely useful here, as they essentially capture the same information in half the file size.
For more context, please read the Complete Events section of Trace Event Format Document. Theoretically, this should reduce the file size by a factor of 2 ๐
Keeping track of current and last active nodes, we can clearly determine all the events that are starting and ending at a particular timestamp.
A way to implement this would be to add all the start events (along with their timestamp of starting) in a hashMap, and only add the chrome events object after they have completed (duration can be obtained by subtracting end/current and start timestamps)
when will ios support add because from react-native 0.0.64 Hermes has added in ios
The Trace Event Format has listed down the various chrome events and how they are understood by the Chrome Profiler.
The Chrome Profiler consumes this profiling data in the JSON Array Format while the Hermes Profile is generated in the JSON Object Format. We might have made an oversight in assuming that the traceEvents generated by the Hermes Profiler are going to have phases assigned similar to Chrome Profiler, however this is not the case.
The phases in the case of the Hermes Profile need to be derived from the Samples and Stack Frames Properties in the Hermes Profile. This is where things are accumulated from lower level OS Kernels and we need to make sense of this data.
TBD : 2nd point, needs more discussion
Profile Chunks
Reproduce steps:
Input: sampling-profiler-trace3882871943179202698.cpuprofile
Output (unzip): chrome-supported.json.zip
Transform script:
/**
* Used to transform hermes profiler outputs to supported by chrome dev tools.
* https://github.com/react-native-community/hermes-profile-transformer
*/
const transformer = require('hermes-profile-transformer').default
const { writeFileSync } = require('fs')
const hermesCpuProfilePath = 'sampling-profiler-trace3882871943179202698.cpuprofile'
transformer(
// profile path is required
hermesCpuProfilePath
// source maps are optional
// sourceMap,
// sourceMapBundleFileName
)
.then((events) => {
// write converted trace to a file
return writeFileSync('./chrome-supported.json', JSON.stringify(events, null, 2), 'utf-8')
})
.catch((err) => {
console.log(err)
})
First I followed https://reactnative.dev/docs/hermes/
then https://reactnative.dev/docs/profile-hermes
Recording a Hermes sampling profile seems to succeed
(hermes-profile-transformer is in my node-modules at version 0.0.6)
Then the command to convert and transfer the Hermes tracing profile fails as follows:
$ npx react-native profile-hermes ./dev
info Downloading a Hermes Sampling Profiler from your Android device...
info No filename is provided, pulling latest file
info File to be pulled: sampling-profiler-trace552874595700445033.cpuprofile
error Cannot read properties of undefined (reading 'pid').
TypeError: Cannot read properties of undefined (reading 'pid')
at Function.collectProfileEvents (/Users/dev/app/node_modules/hermes-profile-transformer/dist/hermes-profile-transformer.cjs.development.js:315:28)
at /Users/dev/app/node_modules/hermes-profile-transformer/dist/hermes-profile-transformer.cjs.development.js:517:43
at async downloadProfile (/Users/dev/app/node_modules/@react-native-community/cli-hermes/build/profileHermes/downloadProfile.js:160:24)
at async Object.profileHermes [as func] (/Users/dev/app/node_modules/@react-native-community/cli-hermes/build/profileHermes/index.js:28:5)
at async Command.handleAction (/Users/dev/app/node_modules/@react-native-community/cli/build/index.js:192:9)
info Run CLI with --verbose flag for more details.
$ react-native info
info Fetching system and libraries information...
(node:25683) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
System:
OS: macOS 12.4
CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
Memory: 857.19 MB / 16.00 GB
Shell: 5.1.16 - /usr/local/bin/bash
Binaries:
Node: 16.14.2 - /usr/local/bin/node
Yarn: 1.22.15 - /usr/local/bin/yarn
npm: 8.5.0 - /usr/local/bin/npm
Watchman: Not Found
Managers:
CocoaPods: 1.11.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5
Android SDK: Not Found // but it is present, API level 30
IDEs:
Android Studio: 2021.1 AI-211.7628.21.2111.8309675
Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild
Languages:
Java: 11.0.14.1 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 17.0.2 => 17.0.2
react-native: 0.67.2 => 0.67.2
react-native-macos: Not Found
npmGlobalPackages:
*react-native*: Not Found
EDIT:
one workaround is to use chrome://tracing to inspect profile
Hello, I'm trying to profile a react-native app, I followed the official documentation on how to pull and transform the Hermes tracing profile.
So once the profile is recorded I'm running this:
npx react-native profile-hermes \
--sourcemap-path './android/app/build/intermediates/sourcemaps/react/debug/index.android.bundle.packager.map'\
~/Downloads
It outputs this:
warn Package expo-modules-core has been ignored because it contains invalid configuration. Reason: "dependency.platforms.ios" must be of type object
info Downloading a Hermes Sampling Profiler from your Android device...
info No filename is provided, pulling latest file
info File to be pulled: sampling-profiler-trace1250977739574747452.cpuprofile
success Successfully converted to Chrome tracing format and pulled the file to /Users/olivier.freyssinet/Downloads/sampling-profiler-trace1250977739574747452-converted.json
And here attached you can file the output .json. I don't know about the formatting but it seems to contain actual data that reflects what's going on in my app, so then it's just a matter of parsing it I guess.
So then I try to load it in the performance tab of Chrome Version 109.0.5414.119 (Official Build) (arm64)
It seems to be parsing the whole file but then nothing is displayed and I get the following error in the console (three times):
17:30:02.957 Failed to find browser main thread in trace, some timeline features may be unavailable
17:30:02.958 Failed to find browser main thread in trace, some timeline features may be unavailable
17:30:02.982 Failed to find browser main thread in trace, some timeline features may be unavailable
Another person who is trying on a Linux computer gets this slightly more explicit error:
Error parsing trace data: no TracingStartedInBrowser event found
"hermes-engine": "0.11.0"
react-native info
outputSystem:
OS: macOS 12.5.1
CPU: (10) arm64 Apple M1 Max
Memory: 96.39 MB / 32.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.15.0 - /usr/local/bin/node
Yarn: 1.22.18 - /opt/homebrew/bin/yarn
npm: 8.5.5 - /usr/local/bin/npm
Watchman: 2022.09.19.00 - /opt/homebrew/bin/watchman
Managers:
CocoaPods: 1.11.3 - /usr/local/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1
Android SDK:
API Levels: 29, 30, 31, 32, 33
Build Tools: 28.0.3, 30.0.2, 30.0.3, 31.0.0, 32.0.0, 32.1.0
System Images: android-31 | Google APIs ARM 64 v8a, android-32 | Google APIs ARM 64 v8a, chromeos-67 | Chrome OS 67
Android NDK: 22.1.7171670
IDEs:
Android Studio: 2021.1 AI-211.7628.21.2111.8309675
Xcode: 14.2/14C18 - /usr/bin/xcodebuild
Languages:
Java: 11.0.15 - /usr/bin/javac
npmPackages:
@react-native-community/cli: ^7.0.1 => 7.0.4
react: ^17.0.2 => 17.0.2
react-native: 0.68.5 => 0.68.5
react-native-macos: Not Found
npmGlobalPackages:
*react-native*: Not Found
Thanks in advance for any help! ๐
The idea is to isolate similar events and assign phases to them after reviewing these similar events
The following fixes need to be made
We need to test the following
As discussed with @axemclion, we would want to have only three categories
This needs to be done so that the package can be used by React Native CLI.
Rather than index.bundle being the name of the file, we want the corresponding file name in the event name (Eg: __guard(http://10.0.2.2:8081/index.bundle?platform=android&dev=true&minify=false:2702:15)
=> __guard(fileName of this function)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.