perf: improve column handling speed, fix infinite loops #1597
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.
The primary change here is that the column calculation algorithm now attempts to render columns as if they were the full remaining height on the page, rather than to render the entire content regardless of how long the page is.
The worst-case behavior is effectively the same as that of the previous algorithm (as at least one additional pass would be required to determine how high balanced columns should be, but this applies in both cases), but if content would not fit on the page, this can bail and set the page immediately, rather than continuing significantly more calculations.
As an associated benefit, this closes #1020, as we now handle multiple column breaks (which would force a page break) correctly. A test for this behavior is included.
In unscientific tests, this appears to be a significant speedup in worst-case column calculations, for example taking a 100+ page multi-column render from 45 minutes to under two minutes. A more realistic document render time was cut by about 50% (from a starting point of ~five minutes).
It is certainly plausible that there exist better algorithms for determining column heights (such as calculating possible breakpoints for children), but this provides significantly improved execution time over the current algorithm in both pathological and real-world tests, with minimal algorithmic changes. I certainly won't be offended if this gets entirely rewritten in the path to v55/56, but it might be nice to have in the meantime.