Kunde21 / markdownfmt

Like gofmt, but for Markdown.
MIT License
55 stars 7 forks source link

perf: Track indentation during traversal #64

Closed abhinav closed 1 year ago

abhinav commented 1 year ago

The markdown renderer currently relies on lineIndentWriter calculating the indentation for a write by traversing the ancestors of a node. This is fairly expensive and causes recomputation of prior information.

This changes lineIndentWriter to have PushIndent/PopIndent methods which nodes call during traversal of the AST. For example, blockquote can call PushIndent("> ") when entering and PopIndent() when exiting, to inform the writer of indentation of text within it.

Results

name                                   old time/op    new time/op    delta
Render/example1.input.md-2               30.0µs ± 0%    28.5µs ± 1%   -4.90%  (p=0.016 n=4+5)
Render/headers.same.md-2                 36.5µs ± 2%    36.5µs ± 2%     ~     (p=1.000 n=5+5)
Render/html.input.md-2                   11.9µs ± 5%    12.0µs ± 1%     ~     (p=0.151 n=5+5)
Render/lists.input.md-2                  84.3µs ± 7%    52.6µs ± 1%  -37.64%  (p=0.016 n=5+4)
Render/lists.same.md-2                   31.3µs ± 0%    22.6µs ± 1%  -27.69%  (p=0.008 n=5+5)
Render/nested-code.same.md-2             3.77µs ± 3%    3.87µs ± 5%     ~     (p=0.286 n=4+5)
Render/reference.same.md-2                170µs ± 3%     163µs ± 3%   -4.10%  (p=0.016 n=5+5)
Render/successive.input.md-2             8.54µs ± 1%    8.80µs ± 1%   +3.14%  (p=0.008 n=5+5)
Render/things-inside-blocks.same.md-2     111µs ± 3%     108µs ± 6%     ~     (p=0.310 n=5+5)
Render/widechar.input.md-2               4.81µs ± 1%    4.85µs ± 2%     ~     (p=0.421 n=5+5)

name                                   old alloc/op   new alloc/op   delta
Render/example1.input.md-2               2.58kB ± 0%    2.64kB ± 0%   +2.17%  (p=0.008 n=5+5)
Render/headers.same.md-2                 8.72kB ± 0%    9.22kB ± 0%   +5.69%  (p=0.008 n=5+5)
Render/html.input.md-2                   2.13kB ± 0%    2.17kB ± 0%   +1.50%  (p=0.008 n=5+5)
Render/lists.input.md-2                  3.34kB ± 0%    1.32kB ± 0%  -60.43%  (p=0.008 n=5+5)
Render/lists.same.md-2                   1.12kB ± 0%    0.56kB ± 0%  -50.00%  (p=0.008 n=5+5)
Render/nested-code.same.md-2               288B ± 0%      320B ± 0%  +11.11%  (p=0.008 n=5+5)
Render/reference.same.md-2               20.6kB ± 0%    21.6kB ± 0%   +5.06%  (p=0.016 n=5+4)
Render/successive.input.md-2               328B ± 0%      344B ± 0%   +4.88%  (p=0.008 n=5+5)
Render/things-inside-blocks.same.md-2    16.1kB ± 0%    16.9kB ± 0%   +5.07%  (p=0.008 n=5+5)
Render/widechar.input.md-2               1.12kB ± 0%    1.18kB ± 0%   +5.72%  (p=0.008 n=5+5)

name                                   old allocs/op  new allocs/op  delta
Render/example1.input.md-2                 87.0 ± 0%      74.0 ± 0%  -14.94%  (p=0.008 n=5+5)
Render/headers.same.md-2                    180 ± 0%       180 ± 0%     ~     (all equal)
Render/html.input.md-2                     28.0 ± 0%      28.0 ± 0%     ~     (all equal)
Render/lists.input.md-2                     416 ± 0%       153 ± 0%  -63.22%  (p=0.008 n=5+5)
Render/lists.same.md-2                      142 ± 0%        59 ± 0%  -58.45%  (p=0.008 n=5+5)
Render/nested-code.same.md-2               8.00 ± 0%      9.00 ± 0%  +12.50%  (p=0.008 n=5+5)
Render/reference.same.md-2                  587 ± 0%       518 ± 0%  -11.75%  (p=0.008 n=5+5)
Render/successive.input.md-2               18.0 ± 0%      18.0 ± 0%     ~     (all equal)
Render/things-inside-blocks.same.md-2       467 ± 0%       429 ± 0%   -8.14%  (p=0.008 n=5+5)
Render/widechar.input.md-2                 21.0 ± 0%      21.0 ± 0%     ~     (all equal)

List rendering is significantly faster now. There's a sub-microsecond increase on one of the cases, but it appears to be worth it.