Profiling Server-Side Renderer In RORP
This guide helps you profile the server-side code running in RORP node-renderer. It may help you find slow parts or bottlenecks in code.
This guide uses the RORP dummy app in profiling the server-side code.
Profiling Server-Side Code Running On Node Renderer
-
Run node-renderer using the
--inspectnode option.Open the
spec/dummy/Procfile.devfile and update thenode-rendererprocess to run the renderer usingnode --inspectcommand. Change the following linenode-renderer: RENDERER_LOG_LEVEL=debug yarn run node-rendererTo
node-renderer: RENDERER_LOG_LEVEL=debug RENDERER_PORT=3800 node --inspect client/node-renderer.js -
Run the App
bin/dev -
Visit
chrome://inspecton Chrome browser and you should see something like this: -
Click the
inspectlink. This should open a developer tools window. Open the performance tab there -
Click the
recordbutton -
Open the web app you want to test and refresh it multiple times. We use the React on Rails Pro dummy app for this tutorial. So, we will open it in the browser by going to http://localhost:3000
-
If you get any
Timeout Errorwhile visiting the page, you may need to increase thessr_timeoutin the Ruby on Rails initializer file. Running node-renderer using the--inspectflag makes it slower. So, you can increase thessr_timeoutto10 secondsby adding the following line toconfig/initializers/react_on_rails_pro.rbfileconfig.ssr_timeout = 10 -
Stop performance recording
-
You should see something like this
Profile Analysis
You can see that there is much work done during the first request because it contains the process of uploading the component bundles and executing the server-side bundle code.
By zooming into it, you can see the function that’s called buildVM (you can also search for it by clicking Ctrl+f and type the function name)
All code that runs later inside that code context calls the runInContext function. Like this code that calls renderToString to render a specific react component
To check the profile of other requests, zoom into any of the following spots of work
You should find a call to serverRenderReactComponent
If you can’t find any requests coming to the renderer server, component caching may be the cause. You can try to disable React on Rails caching by adding the following line to config/initializers/react_on_rails_pro.rb file
config.prerender_caching = falseProfiling Renderer With High Loads
To see the renderer behavior while there are many requests coming to it, you can use the ApacheBench (ab) tool that lets you make many HTTP requests to a specific end points at the same time.
-
The
ApacheBench (ab)is installed on macOS by default. You can install it on Linux by running the following commandsudo apt-get install apache2-utils -
Do all steps in
Profiling Server-Side Code Running On Node Renderersection except the step number 6. Instead of opening the page in the browser, let theabtool make many HTTP requests for you by running the following command.ab -n 100 -c 10 http://localhost:3000/ -
Now, we you open the noder-renderer profile, you will see it very busy responding to all requests
-
Then, you can analyze the renderer behavior of each request as stated in
Profile Analysissection.
ExecJS
React on Rails Pro supports profiling with ExecJS starting from version 4.0.0. You will need to do more work to profile ExecJS if you are using an older version.
If you are using v4.0.0 or later, you can enable the profiler by setting the profile_server_rendering_js_code config by adding the following line to the ReactOnRails initializer.
config.profile_server_rendering_js_code = trueThen, run the app you are profiling and open some pages in it.
You will find many log files with the name isloate-0x*.log in the root of your app. You can use the following command to analyze the log files.
rake react_on_rails_pro:process_v8_logsYou will find all log files are converted to profile.v8log.json file and moved to the v8_profiles directory.
You can use speedscope to analyze the profile.v8log.json file. You can install speedscope by running the following command
npm install -g speedscopeThen, you can analyze the profile by running the following command
speedscope /path/to/profile.v8log.jsonProfiling ExecJS with Older Versions of React on Rails Pro
If you are using an older version of React on Rails Pro, you need to do more work to profile the server-side code running in the ExecJS.
If you are using node as the runtime for ExecJS, you can enable the profiler by adding the following code on top of the ReactOnRailsPro initializer.
class CustomRuntime < ExecJS::ExternalRuntime
def initialize
super(
name: 'Custom Node.js (with --prof)',
command: ['node --prof'],
runner_path: ExecJS.root + '/support/node_runner.js'
)
end
end
ExecJS.runtime = CustomRuntime.newIf you are using V8 as the runtime for ExecJS, you can enable the profiler by adding the following code on top of the ReactOnRailsPro initializer.
class CustomRuntime < ExecJS::ExternalRuntime
def initialize
super(
name: 'Custom V8 (with --prof)',
command: ['d8 --prof'],
runner_path: ExecJS.root + '/support/v8_runner.js'
)
end
endAfter adding the code, you can run the app and open some pages in it. You will find many log files with the name isloate-0x*.log in the root of your app. You can use the following command to analyze any log file.
node --prof-process --preprocess -j isolate*.log > profile.v8log.json
npm install -g speedscope
speedscope /path/to/profile.v8log.json