Reduce number of content sequences to speed up compile time #33
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.
Consider the test example:
In order for it to compile, the recursion limit needs to be raised to
369
and then, it takes roughly25s
to compile on my machine. That's because the compiler needs to "prepare" for every possible sequence of contents. However, most of them are very unlikely to occur.This PR reduces these by "crawling back" in the content tree when the section is not found in the current content. Effectively, the current content is forgotten and not used in the further content sequences. In other words, the sections in the content sequence always lie on a path in the content tree. All of the previous contents are the ancestors of the current one. This decreases the number of possible content sequences from quartic (the length of the content sequence is 4) to linear, eradicates the need to raise the recursion limit and the compilation is significantly faster: roughly
2.5s
on my machine.The mustache specification does not mention using sections from the parent contexts at all, so this is kind of an extra feature anyway. All tests are passed and in the majority of cases, the behaviour remains the same. Then, there are some edge differences. Consider the structs from the example.
{{#a}} {{#b}} {{bin1}} + {{ain}} + {{bin2}} {{/b}} {{/a}}
now doesn't render
{{ain}}
, as it's not found inb
, nor in any of the parent contents in the content tree. We can always return to the previous behaviour by using{{#a}} {{#b}} {{bin1}} + {{#a}} {{ain}} {{/a}} + {{bin2}} {{/b}} {{/a}}
.This is quite verbose, on the other hand it makes clear in which content the variable is expected.
However, mostly a much simpler solution would suffice:
{{#a}} {{#b}} {{bin1}} {{/b}} + {{ain}} + {{#b}} {{bin2}} {{/b}} {{/a}}
,or even
{{#b}} {{bin1}} + {{#a}} {{ain}} {{/a}} + {{bin2}} {{/b}}
.The only case where a workaround of this sort is not possible is when
a
andb
are both lists, but my imagination is not sufficient to conceive an actual example of where a construct like that would be desired. I don't think it's required by the specification, as the sections form parent contexts are not mentioned there, and speeding the compilation up, as well as reducing the binary size provides more practical advantages.