Skip to content

CST memory optimization - #2191

Open
spoenemann wants to merge 11 commits into
mainfrom
cst-memory-opt
Open

CST memory optimization#2191
spoenemann wants to merge 11 commits into
mainfrom
cst-memory-opt

Conversation

@spoenemann

@spoenemann spoenemann commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

This PR aims at improving Langium's memory usage, which was found to be relatively high in this article. The Conrete Syntax Tree (CST) implementation is the main reason for this. These measures have been applied:

  • root is no longer stored in all CST nodes, but derived by walking up the container hierarchy.
  • range is no longer stored in leaf CST nodes, but created on demand from integer values.
  • Optional properties (especially _astNode and _rangeCache) are initialized with undefined so the V8 engine includes them in the finalized object layout (this avoids the overhead of a separate PropertyArray for properties added later).
  • content is now a readonly array and must be manipulated via the CstNodeBuilder so we avoid the CstNodeContainer overhead.

The first two changes save memory by doing a bit more computation for the root, text, and range properties, which mostly affects LSP-related services. The overhead of these computations is virtually negligible, and the benefits of the changes outweigh it by far as shown in the benchmarks below.

I created four benchmarks to measure the impact of these changes on the CST size, parsing, and document building:

  • cst-node-memory-benchmark.ts measures the memory usage of a synthetically generated CST
    • → −49 % memory compared to main 🎉
  • cst-parse-memory-benchmark.ts measures the memory usage of a parsed CST
    • → −45 % memory compared to main 🎉
  • parser-time-benchmark.ts measures the execution time of the parser
    • → −33 % parse time compared to main 🎉
  • workspace-build-benchmark.ts measures the execution time and heap size of a full workspace build
    • → −14 % build time and −19 % heap size compared to main 🎉

@spoenemann
spoenemann requested a review from msujew July 22, 2026 15:58
@cdietrich

cdietrich commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

in my measurements we see only 35% memory gain (on the total heap) but this is still a huge improvement. for pure cst it is almost 50%

Comment thread CONTRIBUTING.md
npm run coverage # run tests with coverage report
```

You can also run the tests of a single package, e.g. `npm test --workspace=langium`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this correct?

npm test --workspace=langium
npm error Lifecycle script test failed with error:
npm error workspace langium@4.3.0
npm error location /Users/dietrich/git/langium/packages/langium
npm error Missing script: "test"
npm error
npm error To see a list of scripts, run:
npm error npm run --workspace=langium@4.3.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe
npm test -- packages/langium

Comment thread CONTRIBUTING.md
## Prerequisites

For developing Langium, you require at least Node.js version 16 and at least npm version 7.7.0 to be able to use npm workspaces.
For developing Langium, you require at least Node.js version 20.10.0 (see the `engines` entry in [package.json](./package.json)). The npm version bundled with it supports npm workspaces, which this repository relies on.

@cdietrich cdietrich Aug 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the nvmrc we have 24, package json requires 22

Comment thread CONTRIBUTING.md
When you add a dependency to a `package.json` npm resolves this from the configured registry (default is [registry.npmjs.org](https://registry.npmjs.org/)). In other dependency management systems you can create something like a dev or snapshot version and install it locally, but this is not possible as such with npm. If you want to achieve a similar behavior you need to link your packages globally (global refers to you user's account scope, local refers to the project's scope). When you do this you forcefully overwrite what was downloaded from the npm registry. Incrementing the version of Langium itself will lead to problems, because npm will not be able to resolve those from its registry and therefore fail any install attempts in projects referring to Langium.

If you execute `npm install` on the top-level of your Langium checkout all dependencies will be gathered locally inside `node_modules` and all four packages or sub-projects will be built. **Warning**: Do not run npm install directly inside the four Langium packages as it will mess up dependency resolution once you link packages globally.
If you execute `npm install` on the top-level of your Langium checkout all dependencies will be gathered locally inside `node_modules` and all packages or sub-projects will be built. **Warning**: Do not run npm install directly inside the individual Langium packages as it will mess up dependency resolution once you link packages globally.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

install wont build

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants