Application performance after implementing react-isomorphic-data
chris-hinds opened this issue · comments
We've been looking at introducing react-isomorphic-data to Simorgh and have noticed that just implementing this library and not including any extra data fetches has nearly doubled the latency/response time of the application. Including 1 extra data fetch nearly triple's the response time when server side rendering.
Is this something you have observed before? or something you are aware of?
This is our application running against the latest (master) branch without the library.
Stat | 2.5% | 50% | 97.5 | 99% | Avg | Stdev | Max |
---|---|---|---|---|---|---|---|
Latency | 223 ms | 276 ms | 425 ms | 541 ms | 288.31 ms | 53.61 ms | 648.6 ms |
This is the application with this library introduced, however with no extra data fetching.
Stat | 2.5% | 50% | 97.5 | 99% | Avg | Stdev | Max |
---|---|---|---|---|---|---|---|
Latency | 415 ms | 478 ms | 995 ms | 1088 ms | 513.42 ms | 120.85 ms | 1112.93 ms |
And this is with 1 data fetch using the useData()
hook
Stat | 2.5% | 50% | 97.5 | 99% | Avg | Stdev | Max |
---|---|---|---|---|---|---|---|
Latency | 619 ms | 737 ms | 1239 ms | 1329 ms | 769.81 ms | 142.54 ms | 1363.48 ms |
This is interesting. I did not expect this to double the latency.
I will try to create a simple reproduction and profile them to see what might be going on, and what can be improved.
EDIT (Explanation add at #52 (comment))
Actually, it makes sense. We are doing a prepass before doing the actual render, so that alone should almost double the processing time.
For the adding useData()
hook, I suspect it might be affected by the API latency, data size, and the data processing.
Thanks @jackyef if you do spot anything obvious please let me know, we are happy to contribute fixes/improvements to this library.
@hindsc52 For the one with 1 useData()
hook, what is the latency of the endpoint you are fetching from? Could it be around ~200ms?
So, after doing some profiling, I see that the task that takes the longest is code from react-ssr-prepass
. This is basically walking through the app tree and resolve thrown promises (Suspense) as it sees them.
As shown in the screenshots above, the longest 2 block of tasks (other than react's own renderToString
and renderDOM
) is from react-isomorphic-data
line 168. Which contains the code from react-ssr-prepass
.
Since the alternative is to call renderToString
multiple times, I tried to do a simple benchmark.
┌─────────┬──────────────────────────┬───────────────────┬───────┐
│ (index) │ name │ average │ stdev │
├─────────┼──────────────────────────┼───────────────────┼───────┤
│ 0 │ 'react-ssr-with-prepass' │ 150.1085802333333 │ 22.79 │
│ 1 │ 'react-ssr-isodata' │ 156.2910870333333 │ 19.12 │
│ 2 │ 'react-ssr-3-times' │ 210.0336295333333 │ 5.55 │
└─────────┴──────────────────────────┴───────────────────┴───────┘
Explanation:
react-ssr-with-prepass
is doingawait prepass(app)
before doingrenderToString(app)
;react-ssr-isodata
is doingawait renderToStringWithData(app)
, without anyuseData
hooks in the app.react-ssr-3-times
is just callingrenderToString(app)
3 times.
So, react-ssr-with-prepass
is the fastest out of the 3. react-ssr-isodata
is slightly slower, which is expected because it uses prepass
internally. With more hooks, the number could be worse depending on the API latency, data size, and how the data is processed.
react-ssr-3-times
is done to simulate rendering the App 3 times to collect all data, but in real world cases, this could be more, with the minimum being 2.
Note: this benchmark renders 64472 divs recursively, which is quite extreme and does not usually happen in real world app. Nevertheless, we can take some insights from it.
You can run the benchmark here: https://github.com/jackyef/react-isomorphic-data-benchmark
Summary
I would say if your app previously do fetching before calling renderToString
1 time, you will surely see performance degradation. I guess that would be the cost of having the ability to declare data requirement in the components + automatic handling of nested and conditional data requirement.