Opened 17 years ago
Closed 17 years ago
#7691 closed defect (bug) (fixed)
autosave newer version check can be slow enough to cause edit tab to time out
| Reported by: |
|
Owned by: | |
|---|---|---|---|
| Milestone: | 2.7 | Priority: | normal |
| Severity: | normal | Version: | |
| Component: | Autosave | Keywords: | has-patch |
| Focuses: | Cc: |
Description
in edit-form-advanced.php there's a call to wp_text_diff() that checks for a newer autosave revision that is different (around line 48). Under certain circumstances this can cause a loop that will eat CPU for several minutes and prevent the edit post tab from opening.
Specifically it happens if two revisions are very long, have many lines, and every line is different between the two revs. I can reproduce this in unit testing with two different revisions, each with 10,000 lines of 50 characters. The real-world circumstances that triggered this was a very long post (approx 750kb) where one revision contained HTML tags, and the other revision had html special chars converted to entities. That caused virtually every line to be different.
There are three separate issues here:
- edit-form-advanced.php calls wp_text_diff() (a heavyweight function for displaying the differences between posts) when all it really needs is a fuzzy text comparison function.
- wp_text_diff() calls WP_Text_Diff_Renderer_Table, which is very inefficient under these circumstances. I don't know enough about that code to know the cause or appropriate fix, but it seems to get stuck in the compute_string_distance() loop at the top of interleave_changed_lines(). It's not an infinite loop as far as I can tell, just very inefficient in this particular case.
- Under some unknown circumstances, revisions are saved with special chars entity-encoded. That will screw with versioning diffs even if the above two issues are fixed.
Working on a fix for 1. I'll leave 2 and 3 for folks with specific knowledge about those things.
Attachments (1)
Change History (8)
#2
@
17 years ago
Perhaps we can call normalize_whitespace() dif_normalize_whitespace() as if it's run on the content before autop, it would break most P tags. Or maybe better to normalize it properly, something like
$str = preg_replace('/(\r?\n|\r)/', '\n', $str);
would leave 2 "\n" where needed (this is only needed for the HTML editor, TinyMCE handles it internally). Also may need to replace some other whitespace chars like U+00a0, U+202f, etc. (some browsers when set in certain encodings can insert these when in designMode/contentEditable).
#3
@
17 years ago
- Cc dougal added
I ran across this in a real-world situation, as well. A client has a post that they are constantly re-editing with updates on a political issue. There are nearly 140 revisions so far, and about 19K of html text in the current revision. On the test server, everything is fine, but on the production servers, which are under load, trying to edit this post will time out, more often than not.
In the 'newer autosave' check, is it really necessary to use wp_text_diff()? Why not use a more direct string-to-string equality comparison? Or, as suggested above, maybe use some simpler normalization before comparison?
My current work-around for this problem was to bump up the PHP max_execution_time variable. But I think this is something that definitely needs attention in the WP core. A 19K post isn't so far out of the norm that it should run into a performance problem like this.
It might be good if there was at least some way to shortcut the text diff with some filters and/or flags? Something short of replacing the whole pluggable function.
#5
@
17 years ago
We can't use a string equality as the check. Mostly because the Visual and HTML editors save their whitespace differently.
The normalize_whitespace() function will probably work.
Also, azaozz, this function won't be used in either displaying or saving content. Just when comparing two strings.
fix attached; lightly tested only.