matrix-org / matrix-org/matrix-viewer

Running the Hydrogen render process in `child_process` is slow

Open
#49 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-performance A-SSR A-tracing T-Enhancement
Dominant language
JavaScript
Stars
84
Forks
10
PR merge metrics
No merged PRs in 30d

Description

Spawning from https://github.com/matrix-org/matrix-public-archive/pull/44 which added more tracing and made it obvious how much slow child_process is over the base vm script.runInNewContext(...)


Soo, how slow is running in the child_process?

In https://github.com/matrix-org/matrix-public-archive/pull/36, we started wrapping our whole rendering Hydrogen vm flow in a child_process because using a Node.js vm context doesn't have a way to stop the process (it just keeps running). With the child_process we can kill it when we choose after we get the HTML result.

Now with this timing from https://github.com/matrix-org/matrix-public-archive/pull/44, we can also get some insight into how bad of a performance hit it is to run the Hydrogen render in the child_process is. It seems to be a lot slower: ~50ms vs 360ms.

// Use the `vm` directly to see how fast it is
const _renderHydrogenToStringUnsafe = require('../hydrogen-render/3-render-hydrogen-to-string-unsafe');
const hydrogenHtmlOutput = await _renderHydrogenToStringUnsafe({ /* renderData */ });

(see server/README.md for enabling tracing in the app)

Without child_process (renderHydrogenToString took 43ms) With child_process (renderHydrogenToString took 397ms)
Jaeger trace where renderHydrogenToString takes 43ms Jaeger trace where renderHydrogenToString takes 400ms

I wonder how much of the slowness is the disk read every time it reads in the script to run?

We could test this theory by inlining the script directly in https://github.com/matrix-org/matrix-public-archive/blob/fd00fec6f1f91ea55fe59b05f0658318c2738f42/server/hydrogen-render/3-render-hydrogen-to-string-unsafe.js#L95-L98

Should we switch away from child_process?

Maybe.

We could use the vm script.runInNewContext(...) timeout option and just accept that it will be living for 5 seconds (or whatever we timeout we choose) before it dies. We already choose to kill the child_process after 5 seconds if it takes too long since we expect the Hydrogen render part to be fast.

Or maybe abuse the vm script.runInNewContext(...) breakOnSigint option and send a SIGINT to kill it. Need to be careful not to kill our main process.

Is it possible just to reset and render Hydrogen over and over with the same VM context? We could do a similar thing and keep the child_process alive and share for all renders.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in server/hydrogen-render/3-render-hydrogen-to-string-unsafe.js, especially lines 95–98, and use server/README.md to enable tracing. Compare child_process overhead with direct vm execution and the proposed timeout or context alternatives; the issue currently provides no single implementation or definition of done.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
backend, performance
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.