perf: add string flattening to reduce retained memory (node only) #162
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Changes
Fixes #161
As discussed in #161, this PR applies a performance optimization to reduce the memory footprint of parsed templates that are held in memory. The implementation tries to "flatten" the string's memory representation.
After a few trials, the only implementation that works in Node 8.x, 10.x and 12.x is to convert the string to a
Bufferinstance and back to a string.This PR also adds a memory footprint benchmark suite.
Performance impacts
Here are the results of running the benchmarks before/after the change:
Node v8.16.1
Before change
After change
Node v10.16.3
Before change
After change
Node v12.11.1
Before change
After change
Summary
There seems to be a negative performance impact (ops per sec) that is most noticeable on Node.js 8.x. For 10.x and 12.x, the impact is less obvious, some tests perform better, others worse.
The memory footprint improvements are significant for the benchmarked scenario on all three versions of node.
Potential improvements
The overhead of converting to a
Bufferis probably more significant for smaller templates, while the potential gain on the memory side would be smaller. One idea would be to apply the flattening logic only when a given string is longer than some threshold.One option could be to put this optimization behind an option to opt out of this behavior. For example, if a template is used and immediately trashed, there is no gain to reduce the memory footprint as it would get garbage collected quickly. On the contrary, for users that expect to call the template multiple time, the additional latency during parsing is maybe less problematic.
Thanks for sharing any feedback 🙇