hermes icon indicating copy to clipboard operation
hermes copied to clipboard

Profile Hermes in React native app for Release / Production Builds

Open nitish24p opened this issue 2 years ago • 22 comments

Problem

The react native documentation provides a thorough explaination of how to profile RN hermes. However is it possible to do so for a production build, reason being the production build is optimised and minified and will have some DEV checks which wont happen. Is there any way to profile hermes engine of a product / release apk,ipa of RN app. Thanks.

Im sorry if this is the wrong place to discuss this, i tried various channels, but didnt get much help reading online.

Solution

I tried asking this question on Stack overflow https://stackoverflow.com/questions/72457957/cpu-profile-of-hermes-jsc-on-release-apk-of-react-native-app

Also tried reading for this online but wasnt able to get any help, hence wanted to know if this is possible, if so any pointers would helpl.

nitish24p avatar Jun 09 '22 06:06 nitish24p

Hi @nitish24p,

This is the right channel! :)

It is currently possible to use the Hermes CPU (sample) profiler on android (probably the document that you followed). The team is currently working on making this integration better (i.e., easier to use, and available on iOS and android as well), so please bear with us as we prioritize work.

jpporto avatar Jun 15 '22 23:06 jpporto

Hey, @jpporto, the link you mentioned above is for profiling hermes in debug build, and ive tried that and things work well, my question was if the same hermes profiling can be done on a production bundle with sourcemaps, or is this in the pipeline in the near future. Thanks :)

nitish24p avatar Jun 21 '22 19:06 nitish24p

@nitish24p,

It is in the pipeline. The team has made a priority to support the devx while using hermes, so this should be happening soon. :)

jpporto avatar Jun 21 '22 19:06 jpporto

Hi @jpporto , may I ask what should be the best way to profile hermes for start up phase? Would like to generate profiling data before view is rendered, but cannot find it in the doc

xilin avatar Aug 23 '22 16:08 xilin

Is there an update for this?

yolpsoftware avatar Jan 27 '23 02:01 yolpsoftware

@xilin For startup on android you can go to settings and tap on enable profling on startup, then kill your app and you shall see your profiler started, then you can launch your app and do take a sample

nitish24p avatar Jan 29 '23 17:01 nitish24p

@nitish24p which settings do you mean? App settings, Expo Go settings, Android settings?

yolpsoftware avatar Jan 29 '23 21:01 yolpsoftware

For a non expo app when you open the developer menu, you get an option of settings you can check it there

nitish24p avatar Jan 30 '23 15:01 nitish24p

@xilin For startup on android you can go to settings and tap on enable profling on startup, then kill your app and you shall see your profiler started, then you can launch your app and do take a sample

Thanks!

xilin avatar Feb 06 '23 05:02 xilin

@jpporto Any news on profiler support for release bundles or for iOS? Both of those would be very helpful.

evelant avatar Apr 19 '23 15:04 evelant

We are currently implementing some changes that will allow for profiling in release-like optimized builds.

For developer/debug builds, both iOS and Android should be eligible for profiling in current versions of React Native. The quickest way is directly connecting with Chrome Dev Tools:

After launching the application (e.g. npx react-native run-ios), the device can be opened in Chrome at chrome://inspect, and profiling can be started and stopped via the Profiler tab.

profiler

mattbfb avatar Apr 19 '23 17:04 mattbfb

Hey @mattbfb For what version of RN is this available now?

nitish24p avatar Apr 20 '23 17:04 nitish24p

This doesn't appear to be available in version 0.71.7. An iOS simulator doesn't show up in chrome://inspect. The react-native in-app menu has no options for profiling and "open debugger" attempts to open Flipper (which has never worked and is incompatible with most of the react-native ecosystem, thus unusable)

evelant avatar Apr 20 '23 17:04 evelant

AFAIK the only way to profile a hermes application is to use Android, start the profiler from the dev menu, then run react-native profile-hermes to pull and transform it and then open the transformed file with chrome dev tools. It would be really nice if we could just directly use chrome profiler!

evelant avatar Apr 20 '23 17:04 evelant

@nitish24p I'm not sure exactly which version added it, but it should span several recent versions. I have tested in 0.71.1 below. Can you try the following example workflow and share any issues you encounter?

  1. Generate a new project (npx-react-native init ExampleProject) and run it using the suggested command to launch the iOS application. This should open Metro, and the newly-built application.
Screenshot 2023-04-20 at 2 32 20 PM
  1. Navigate to chrome://inspect in Chrome and Inspect the "Hermes React Native" target. This should open Chrome Developer Tools.
Screenshot 2023-04-20 at 2 48 23 PM
  1. Start profiling by selecting "Start" in the "Profiler" tab.
Screenshot 2023-04-20 at 2 48 42 PM
  1. After performing some actions in application (e.g. scrolling around), click "Stop" to collect the trace.
Screenshot 2023-04-20 at 2 49 08 PM

mattbfb avatar Apr 20 '23 19:04 mattbfb

@mattbfb This is on a debug build, is it possible to do the same on a release build?

nitish24p avatar May 11 '23 05:05 nitish24p

@nitish24p The steps outlined above are currently only available in development/debug builds.

mattbfb avatar May 11 '23 15:05 mattbfb

Hello, i am on RN 68.5 (Wont be able to update to latest RN due to legacy Code base). I did a fresh react native init from the cli and made a simple list app. When i click on Profiler from the chrome dev tools i and create a sample, i get an error as mentioned below... I think since the chrome profiling tab has changed to performance, this has started coming

I think the chrome profiler explicitly is trying to search for the Main browser thread and not able to get anything. Earlier there was an option for worker threads, where we could put an option of localhost:8081

chromeerror

nitish24p avatar Jun 12 '23 10:06 nitish24p

Is there any update around the timelines for being able to profile on a production build?

zacharyfmarion avatar Aug 14 '23 21:08 zacharyfmarion

No updates to share at this time, although the issue is still on our radar.

mattbfb avatar Aug 15 '23 20:08 mattbfb

https://github.com/margelo/react-native-release-profiler

Szymon20000 avatar Dec 22 '23 11:12 Szymon20000

Okay want to give some more context on this - the react-native-release-profiler library now allows you to take production profiles. Thank you to @Szymon20000 from Margelo for making this possible!

  1. Install
yarn add react-native-release-profiler
cd ios && pod install
  1. Use
import { startProfiling } from 'react-native-release-profiler';
import Share from 'react-native-share';

// Start profiling as soon as javascript is initialized
startProfiling();

// You could also just make some floating button in the UI to handle this
setTimeout(() => {
  const path = await stopProfiling(device.platform === 'iOS');
  const actualPath = `file://${path}`;

  // OPTIONAL: If in a production environment you can export the profile
  // with react-native-share. If on android and connected to your computer you can 
  // just run the following command:
  // 
  // > npx react-native-release-profiler --fromDownload --appId <your appId>
  await Share.open({
    url: actualPath,
    title: 'Save profile',
    type: 'application/json',
  });
})

  1. Load the profile

Speedscope now supports both the raw hermes format and the transformed format that comes out of hermes-profile-transformer. Because hermes code isn't minified you can just throw a production trace into speedscope and generally see what is going on.

Right now hermes-profile-transformer doesn't support the production hermes format (it uses funcVirtAddr and offset instead of line and col), which means that you can't properly symbolicate production profiles. I have a PR open here to support the production format. For now you can always just patch the library with the diff in that PR and manually transform the profile, which will give you filename, line + col information back:

import transformer from 'hermes-profile-transformer';

// Default sourcemap locations for react-native projects:
// Android sourcemap: android/app/build/generated/sourcemaps/react/<build-variant>/index.android.bundle.map
// iOS sourcemap: ios/build/**/*/main.jsbundle.map
const result = await transformer(profilePath, sourceMapPath, 'index.android.bundle');

// Save the resulting JSON
const outputPath = path.join(
  path.dirname(profilePath),
  `${path.basename(profilePath, path.extname(profilePath))}-transformed.json`,
);

await fs.writeFile(outputPath, JSON.stringify(result, null, 2), 'utf-8');
Screenshot 2024-01-12 at 12 24 38 AM

Hope this helps!

zacharyfmarion avatar Jan 12 '24 08:01 zacharyfmarion