WordPress.org

Make WordPress Core

Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#8957 closed defect (bug) (fixed)

100% CPU, unresponsive javascript when leaving admin "Edit Posts" and "Edit Post" pages

Reported by: _timk Owned by: azaozz
Milestone: 2.8 Priority: normal
Severity: major Version: 2.7
Component: JavaScript Keywords:
Focuses: Cc:

Description

I'm experiencing javascript timeouts and high CPU usage when transitioning between "Edit Posts" and "Edit Post" pages in my WordPress admin interface.

From the post list, when I click an edit link or a link to the next page of posts, Firefox shoots to 100% CPU usage for 5-8 seconds, usually shows the "Unresponsive Script" warning box, and then finally loads the next page. The same happens transitioning from an Edit Post page back to the post list, or reloading the post list page.

If I disable javascript in my browser, the problem goes away.

I think this is related to the number of categories I'm using--I have a couple thousand. The behavior makes me think something client-side is processing that category list on page unload, causing the delay. I realize this is probably a corner case, but I think the admin UI should be able to scale.

I'm a web developer. If someone has an idea on where to look, I may be able to help trace the problem. I'm just not sure where to begin.

Change History (25)

comment:1 DD325 years ago

Does Firefox offer to give you more information about what script is causing the slowdown? What about a Web Developer extension? (I'm not a FF user, so I've got no idea what it offers.. Opera tells me which script is running)

comment:2 _timk5 years ago

Firefox says it's jQuery, which isn't very specific. If I hit the debug button it gives me, it just highlights the generic jQuery library line:

/packer/ JS compressor detected /* !eval(new String(function(p,a,c,k,e,r);)) */

comment:3 _timk5 years ago

I've also tried John Resig's jQuery profiler (http://ejohn.org/blog/deep-profiling-jquery-apps/), but it doesn't record the massive delay.

To me, that's further evidence that it's a page unload problem. The profiler resets anew when the page is reloaded; I'd need to somehow cancel the page unload after the delay, which I don't know how to do. I tried hooking into things like the window unload and onbeforeunload events, but those trigger before the script becomes unresponsive.

comment:4 follow-up: DD325 years ago

AFAIK, There shouldn't be anything running page unload..

comment:5 in reply to: ↑ 4 azaozz5 years ago

  • Keywords reporter-feedback added; unresponsive script javascript cpu browser client categories slow removed

Replying to DD32:

AFAIK, There shouldn't be anything running page unload..

Except maybe the jQuery's own onunload cleanup. Perhaps try using the minified (not the packed) version of jQuery and see if it makes any difference.

comment:6 DD325 years ago

Except maybe the jQuery's own onunload cleanup.

Ah yes.. I didn't think that jQuery might have its own unloader.. Simply because i didnt think there'd be anything in it..

comment:7 _timk5 years ago

I replaced WP's jQuery 1.2.6 with the unpacked, unminified version of 1.2.6, then turned Firefox's script timeout down to a couple of seconds. In the call stack in the debugger, it looks like it is indeed right in the middle of a jQuery unloader on line 2414:

Prevent memory leaks in IE
And prevent errors on refresh with events like mouseover in other browsers
Window isn't included so as not to unbind existing unload events
jQuery(window).bind("unload", function() {

jQuery("*").add(document).unbind(); debugger highlights this line

});

So jQuery is running unbind() on every element in the DOM, which just doesn't scale for documents with large numbers of elements? Why would it need to run unbind() on the entire DOM, anyhow? Are there really jQuery events bound to every element, or is this just a safety catch-all?

comment:8 follow-up: jacobsantos5 years ago

Download the unpacked, unminified version of 1.3.1 and name it 1.2.6 and see if there is any improvement.

comment:9 in reply to: ↑ 8 _timk5 years ago

I tried 1.3.0 before I filed the issue and it's about twice as fast. I don't get the unresponsive script errors, but those page transitions are still unacceptably slow, locking the browser and spiking the CPU usage for about 5 seconds each time.

I'll give 1.3.1 a try to see if it's any better.

comment:10 follow-up: _timk5 years ago

Hmmm... 1.3.1 almost solves the problem. They've changed the unloader:

// Prevent memory leaks in IE
// And prevent errors on refresh with events like mouseover in other browsers
// Window isn't included so as not to unbind existing unload events
jQuery( window ).bind( 'unload', function(){
 for ( var id in jQuery.cache )
   // Skip the window
   if ( id != 1 && jQuery.cache[ id ].handle )
     jQuery.event.remove( jQuery.cache[ id ].handle.elem );
});

Looks like they've changed their internal event handling over to the live-style architecture that's new with 1.3, so they're keeping a list of the events that need to be unbound.

There's little delay on typical navigation between the post list pages and edit pages with 1.3.1, but the delay comes back if you use the Quick Edit function on the Edit Posts page, then navigate away. I'd imagine events are being attached to the category checkboxes for something to do with the edit form, and then they have to be unbound on unload.

Are there plans to move WordPress to jQuery 1.3.x?

comment:11 jacobsantos5 years ago

I thought WordPress was already using 1.3.0 for 2.8. Might be wrong. Take a look at trunk.

comment:12 follow-up: jacobsantos5 years ago

Also, it might be that WordPress isn't using the "live" event system in WordPress and the jQuery plugins most likely aren't either.

comment:13 in reply to: ↑ 12 _timk5 years ago

Looks like 1.3 is in trunk for 2.8, though the jQuery people are recommending 1.3.1 at this point. I'm sure the WP people have already taken notice.

comment:14 in reply to: ↑ 10 ; follow-up: azaozz5 years ago

Replying to _timk:

... but the delay comes back if you use the Quick Edit function on the Edit Posts page, then navigate away. I'd imagine events are being attached to the category checkboxes for something to do with the edit form, and then they have to be unbound on unload.

That's right. When using quick edit there's a keydown event that would save the changes on pressing Enter. Will try removing it from the categories checkboxes. Also jQuery seem to keep all form elements in it's cache (can be seen in Firebug) and since each category has a checkbox, having thousands would slow it down considerably.

Don't see an easy fix or workaround for this. Perhaps can have categories added the same way as tags, by typing the name and using suggest. Could probably have the top 30 or 50 saved in the db as serialized list for fast loading and add a field that would use the suggest functionality for the rest. Could be a bit confusing for the user.

comment:15 azaozz5 years ago

(In [10444]) Remove events from categories chechboxes in quick edit to speed up page unload, see #8957

comment:16 in reply to: ↑ 14 _timk5 years ago

Replying to azaozz:

Don't see an easy fix or workaround for this. Perhaps can have categories added the same way as tags, by typing the name and using suggest. Could probably have the top 30 or 50 saved in the db as serialized list for fast loading and add a field that would use the suggest functionality for the rest. Could be a bit confusing for the user.

I'm not much of a hardcore javascript hacker, but perhaps a parent element could catch events bubbling up from the category checkboxes? Then there would be just one handler to unbind when the page is unloaded.

Thanks for considering this issue, BTW.

comment:17 follow-up: jacobsantos5 years ago

Why not try the new Live Event API in jQuery 1.3?

comment:18 in reply to: ↑ 17 ; follow-up: azaozz5 years ago

Replying to jacobsantos:

Why not try the new Live Event API in jQuery 1.3?

Looking at the jQuery Development mailing list the new Live Event API in jQuery 1.3 is still being refined/fixed. Also not sure that it would speed this up.

@_timk did the change in [10444] fixed it for the Edit Posts screen after using Quick Edit?

comment:19 filosofo5 years ago

If the problem comes from jQuery's unbinding each event bound to thousands of category elements, it seems like event delegation would be a good way to solve it.

comment:20 in reply to: ↑ 18 _timk5 years ago

Replying to azaozz:

@_timk did the change in [10444] fixed it for the Edit Posts screen after using Quick Edit?

Yes, that worked beautifully.

I am still getting some little delay when loading the singular Edit Post page, but it might be acceptable. It looks like it's getting bogged down in wpList.process(). The code seems to be doing something similar to the Quick Edit, adding submit handlers to subform elements.

Looks like the most interesting parent in the call stack while it's spinning is this .each in wp-lists.js.

comment:21 Denis-de-Bernardy5 years ago

close as fixed?

comment:22 hakre5 years ago

  • Keywords reporter-feedback removed
  • Resolution set to fixed
  • Status changed from new to closed

Closed (Interesting Ticket)

comment:23 _timk5 years ago

I think it's still worth looking at the related delay on loading the Edit Post page with a large number of categories. Especially since the following comment appears in the javascript I linked:

// this is all really inefficient

It's just a pause of a second or two on my decently-powered desktop, but it's much longer and crunchier on my netbook.

comment:24 Denis-de-Bernardy5 years ago

@_timk: please open a separate ticket with steps to reproduce, as this ticket is quite long already -- it might get ignored as a result.

comment:25 _timk5 years ago

New ticket opened for the entering-page issue: #9696

Note: See TracTickets for help on using tickets.