The matchBrackets
function within @codemirror/language
is run via the bracketMatchingState
StateField whenever the doc or selection changes.
The following flamegraph was generated using this basic sandbox, modified from the default sandbox to extend the doc
to 2000 lines:
See no-throttling-export.json
for the exported flamegraph.
As you can see from this flamegraph, the matchBrackets
function can take a significant portion of the update cycle, taking 5.21ms out of the 7.39ms dispatch
cycle (70.5%).
The effect is magnified when throttling CPU by 6x:
See 6x-throttling-export.json
for the exported flamegraph.
Here, matchBrackets
takes 24.17ms out of dispatch
's 30.32ms (79.5%).
While investigating, I did find the maxScanDistance
option, and tried setting that to a value much smaller than the default 10000. Unfortunately it appears that matchBrackets
still takes a significant time to run. Here is another flamegraph generated using this modified sandbox which sets maxScanDistance
to 100, and with CPU throttled by 6x:
See max-scan-distance-export.json
for the exported flamegraph.
I can see that by itself, 5ms would not appear to cause a major performance problem, however we have found that this combined with our additional extensions does seem to cause "input lag", where input processing overflows into the next animation frame. We believe (and are confirming) that this occurs more commonly on lower end hardware.
Is it possible that the matchBrackets
implementation could be optimised in some way? I've had a brief look at the code, and couldn't immediately come up with any suggestions.