-
-
Notifications
You must be signed in to change notification settings - Fork 688
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Infinite loop in multi-column layout after first (page-)break-before #1020
Comments
Seems to be broken by adb5216 |
Update for v53: the issue is still current: v53 is still unusable when it comes to multi-column block layouts. Edit: |
I seem to have this issue too. It may be somewhat content-dependent. Our layout uses CSS-implied tables: .row
{
display: table;
}
.col
{
float: left;
} When the loop occurs, weasyprint uses 100% of a cpu core, and ram utilization climbs slowly but steadily. After about 20 minutes, the current example is over 1 GB. v53.4. I can assemble the current document as an example for a developer, but can't really share it publicly. |
I've supplied a reproducer to liZe. |
Are people actually seeing the comments on this issue? |
Going back from this comment, I see three comments from you, then a cross-reference from issue 1549. Are you seeing an actual infinite loop, or is it "just" that multi-column layouts take an excruciatingly long time to render? I have a local test document (which I unfortunately can't share, although I could probably mock up something if necessary) composed primarily of an extremely long list that took about 41 minutes to render inside a I have some profiling from each render, so if I get a chance I'll try to dig into it, but it would be good to nail down exactly what's happening, as I haven't necessary run into it as a |
Well, I know I had given my reproducer at least 20 minutes once, and it's nowhere near as big as yours. I've been watching another trial run for over 90 minutes and it hasn't finished yet, and RAM utilization is up to 3.4 GB. It should come out to be a little less than 50 pages. It is a series of letters, and in effect a two-column layout, with letterhead stuff left, and body right. Only a few of the letters run to a second page. |
To add to the initial bug report: indeed, these 20 lines of HTML/CSS lead to 100% CPU utilization and ever-increasing RAM usage. |
I was curious, so I left this running. After 12 hours of 100% cpu use, it still hasn't finished, but is using nearly 9.5 GB of RAM. But I'm pretty sure that solving this particular halting problem is less relevant than the fact that it's completely impractical if it takes even multiple minutes to render. :) |
Yep, the reproducer at the top of this issue is indeed an infinite loop. You end up looping in here: WeasyPrint/weasyprint/layout/column.py Lines 149 to 162 in e17e536
Effectively, this loop is trying to increase the height of the columns until everything fits between the two columns. It's failing because it will never fit all three required columns into two columns. An easy resolution would be to pop an additional condition in line 209 and 212: WeasyPrint/weasyprint/layout/column.py Lines 209 to 213 in e17e536
We could add I'd have to think for a while on what a good way to resolve that is: perhaps there's some way to make a last-ditch attempt to heighten the remaining columns if we'd have to break pages? @liZe may (hopefully will!) have better ideas. Because that loop is in the column code, though, I don't think it's the cause of the issue you're running into, @drboone. Is there any chance you can try deleting chunks of your HTML + CSS until it works, and then re-add whatever was last to get it to a more minimal (and ideally, sharable) state? I'm not a maintainer, but I've been digging into some performance issues we've been running into at work and might be able to help triage things. |
Okay, for columns, I think the following might work:
I suspect that would also resolve the very long render times I saw with an extremely long multi-column document, as it won't default to slowly expanding and re-layouting every potential height. There's a minor risk of an extra pass if everything would have fit in the first column layout attempted in the current code, but that seems somewhat unlikely in general column usage. |
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 Kozea#1020, as we now handle multiple column breaks (which would force a page break) correctly. A test for this behavior is included.
@liZe If you use this version to generate the test document I sent to you, you'll see that it now fails to scale the logo. It also places the address part of the letterhead much lower than it used to. I'm not sure if this is related to this loop fix, or some other commit. |
Could you please send it again? I didn’t keep it. |
In your email. Thanks for looking! |
I get the same rendering with versions 52.5 and current |
Your merge commit of aschmidtz's changes. The logo is in the top left corner for you, not across most of the page? |
It’s across the whole page, but it was too with versions 52.5 and 54.2. |
046f27b is the version I have been running. It appears my reproducer is not valid for anything but the infinite loop. |
OK, the problem comes from the fact that your document requires presentational hints (the |
Ah, yes, I'd forgotten that for these letters we use the -p option. |
Using WeasyPrint==51, in a 2-column layout, write_pdf() causes an infinite loop when (page-)break-before: always; is applied to more than 1 block:
The same error happens for versions 48, 49 and 50. WeasyPrint==47 works fine. Leaving the second page-break block away, the pdf renders.
The text was updated successfully, but these errors were encountered: