Posting in these forums is disabled. These forums will be available for archive purposes. Please join the new forums at the links below:
|Page 1 of 1||[ 10 posts ]|
I'm stuck, and hoping someone's got a bright idea. IE is giving me the 'Stop running this script?' dialog and I'm not sure why.
Explanation of what my scripts are doing is below. But using IE profiler in developer tools it seems there's a call to Event.getListeners that's taking over 7000ms, way more than anything else. My question is really: does anyone have some tips on working out what's going on? I've tried sticking in various timers and logs in the YUI and my code, and watching the console and the profile reports, but it's not shedding much light.
Here's what's going on:
I have a TabView, containing a form. That form includes some buttons, an autocomplete that's linked to a datatable, and 3 rich text editors. Connection Manager handles the form POST. Caridy's bubbling library processes the results, which is a confirmation page with no js in it.
When the response is loaded the bubbling library destroys whatever's in the way of where the new stuff is going. There's a call to purgeElement with the recursion = true, so it's removing event listeners all the way down. In my case it's about the 12th level down (out of about 15) that's taking the time, and it's that call to getListeners that's taking the time.
But I'm not sure what element this is, and why there's just one that seems to take the time. My suspicion is that it's to do with the datatable, because the delay is longer when I have more rows in the table. (The table has a click event listener to give a delete row button, and two inline editors on two other columns).
On other runs the hang-up seems to be on Event._getCacheIndex, and at different levels down the tree, so I'm not even sure there's going to be an explanation, other than 'oh that's IE for you...'
On top of this, I've also got a cleanup routine that should run before the bubbling process, which destroy()'s the datatable and other YUI widgets in the form.
If anyone's got any suggestions I would be extremely grateful.
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Thu Nov 12, 2009 3:58 pm
Ooooh, that's IE for you...J/K
It's without a doubt the higher level call to purgeElement (true) that you have set. A great resource to read on the dreaded long running script message is by Yahoo's Nicholas Zakas here http://www.nczonline.net/blog/2009/01/05/what-determines-that-a-script-is-long-running/
My best guess being that I haven't seen your work or problem is that when you call purgeElement (true) you have a really deep complex hierarchy of nodes. Since there are so many nodes to process and remove event handlers from, that message is displaying.
what can I say, it's great stuff.
You may also want to try just profiling purgeElement from one child node, etc. Break down the problem into manageable parts.
Wish I could be of more help,
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Fri Nov 13, 2009 3:39 am
I'd seen the first link but missed the second - v interesting.
I think it was the datatable: there's a lot in them. I've changed it a bit so that the datatable is destroy()ed as the form's being submitted (as soon as I've pulled the data out of it), which means that the dispatcher and purgeElement has a lot less work to do once the response has been received.
The whole issue of cleaning up after yourself in an ajax heavy app is quite interesting and rather tricky... We use a lot of widgets, and no page reloads, so it's quite easy to get bogged down. I've not seen anything about this particular relating to YUI (I may not have found it). For example, I might have one button in a dialog, and another on the main screen. When the dialog's submitted the button in the dialog needs to be destroyed, but not the one on the main screen.
Are there any recognised strategies for keeping track of your YUI widgets and what's where, when, and cleaning up afterwards? It'd be interesting to know what other people are doing, or if there are some resources I've not found yet.
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Fri Nov 13, 2009 2:21 pm
In my experience the biggest cause for memory leaks is from circular references and node event handlers that aren't properly removed.
For circular references I get around that issue by using a look up table or hash table strategy, kind like jQuery's $.data.
For node event handlers, I only have them attached to the body element and then I rely on event bubbling and YUI's custom event to do my behavior delegation.
I do this for several reasons,
Caridy's bubbling library can be used to help with the plumbing of the event delegation. He goes into great detail in his post here http://www.yuiblog.com/blog/2007/09/13/bubbling-library-by-caridy/. Also on the home page of Caridy's bubbling library if you haven't checked out the link to Christian Heilmann's article on event driven planning he lays out the foundation for this http://yuiblog.com/blog/2007/01/17/event-plan/.
That's the method I employ on the madness, new techniques keep popping up which is always promising.
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Mon Nov 16, 2009 1:53 am
Thanks for these links and tips. I'd read Caridy's article ages ago and not really understood them (my problem, nothing to do with the article!) - and now wishing I'd 'got it' a bit sooner!
Without diving into all the source code for all the widgets, I guess the widgets don't attach listeners at the body tag level, so I assume it's still necessary to destroy() widgets when they are done with. But I'm going to be moving some of my listeners up the hierarchy and use bubbling.
I've implemented the scheduler approach on my cleanup function that was doing too much, which does seem to be helping. I also realised that I was starting the async request, then calling the cleanup routine, and then the callback was using the Caridy's dispatcher to process the results: which also does some cleaning up. My server was responding too quickly (!) so both my cleanup and the dispatcher purgeElements ended up running at the same time, doing similar things - I think partly causing the problem.
So as well as scheduling the cleanup, I've also created a custom event that fires when the cleaning is done, which is subscribed to by the async stuff so the new content doesn't start to go in until the old is definitely gone. And this means the dispatcher has a lot less to do. But I don't think this is ideal.
So I'm thinking of what other changes to make, and would be interested in any thoughts, and have some questions. I'm thinking aloud a bit here, so apologies in advance!
Firstly, about the clean up. My function was originally a bit like this:
/* and a few more... */
- the 'doing too much function' - which is what I've scheduled.
The alternative I'm thinking of is along the lines of having a 'newPage' customEvent. All my widgets could then subscribe to this and destroy themselves when it fires. This seems like it might be a better solution in terms of code maintainability etc. But won't this end up with a function much like my cleanup() above, just moved somewhere else?
So loading new content would do the async connection; fire the newPage event; when this is done it'll fire a 'pageReady' event, which the async callback will listen for and process the new content.
Anyone have any thoughts?
Thanks very much.
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Tue Nov 17, 2009 10:13 am
I couldn't really tell you which way to roll on this, you're the most familiar with the code and html.
Granted I don't know what widgets you're using, if they're your own or a 3rd party's or you're using YUI widgets.
If you're using YUI widgets, most provide some type of destroy method you can call to clean up any event handlers they may have attached.
If you're using a 3rd party then you're at the whims of their API.
If you have rolled your own widgets out and performance has become a big issue with the purgeElement (true) calls then you may need to go in a different direction. With your own widgets you know what event handlers you're hooking up. Is there any way you could roll a light event manager to do the following:
1. Wrap event subscriptions and store them.
2. Clean up any event subscriptions when you're refreshing data or html elements.
This may be the most brittle, but it allows for better performance.
I suggest it because purgeElement (true) causes the event utility to:
get all event handlers applied to an element and remove them all. Then repeat that for every single descendant html element of that element. The API documentation says "Use with caution." Using this method is like a broad sword, I think you need an approach that's a bit more surgical
Hope that helps, good luck.
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Wed Nov 18, 2009 10:06 pm
Three things come to my mind:
1- Do not walk the dom. Sometimes you don't even know that a certain task is trying to walk the dom. Try to profile your client side application. Check YUI Profiler.
2- Try to avoid having too many listeners, again, sometimes you don't even notice. Profile doesn't help too much on this, that's why it's so hard to clean up.
3- Reuse the widgets. For example: If you use dialogs for example, try to re-use the same instance over and over again, just changing the value of the body, header, footer.
And finally, share a link, and we will TRY to check it for you
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Thu Nov 19, 2009 1:29 am
Thanks Caridy and Dylan,
I'm mid-way through sorting this out (and the weird, possibly related problem I've got with IE not allowing focus on text elements on another thread).
The approach I'm trying now is to create a WidgetContainer object that holds YUI widgets (so each form has one, but not necessarily forms) which can destroy the widgets they know about at the relevant moments. So if a form is submitted, or an ajaxey page reloaded, or dialog closed etc I can destroy what I need to without affecting other widgets on the page. Once I've got this working properly I'll stick it on github or something in case anyone's interested.
There is some duplication with this approach - e.g. YAHOO.widget.EditorInfo also has references to editors (incidentally, it seems that if you destroy an editor it doesn't remove the reference in EditorInfo). Does this matter?
The form that was causing me particular problems had 3 separate rich text editors, two (heavily customised) buttons, an autocomplete linked to a datatable, and some plain form elements. I'm already reusing some things (dialogs and panels like you suggest Caridy), but think I'm also going to have a single application wide RTE that gets used at the relevant times, like Dav's examples.
And I'm going to try and move listeners up the DOM and use bubbling.
I'm going to try and sort out a sandbox of our app so I can post links - at the moment it's all behind passwords...
Thanks as ever,
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Thu Dec 03, 2009 2:29 pm
I've made some progress, thought I'd tell anyone who's interested what I've done.
I've also created a static WidgetManager object, which holds WidgetContainer objects (extensions of element). Each WidgetContainer might hold any number of YUI widgets. So, for example, a WidgetContainer is created based on a form element, and it holds all the button, datatable, autocomplete etc widgets within that form. Another WidgetContainer might hold a datatable and associated context menu.
Then, when a form is submitted the WidgetManager calls a destroy method on the relevant WidgetContainer, which destroys all the widgets it holds. This destruction also happens if a dialog is closed that contains a form, or if the user navigates to another bit of the application etc.
Fortunately, the server side of this has not been too painful, as I'm using Zend Framework, with various classes that create my datatables and forms and things, so the work's been fairly limited. The legwork has been getting the js working for all the various cases that widgets appear, so that only the relevant widgets are destroyed, while others on the page remain while they're still needed.
And finally, I've moved a lot of the listeners up the Dom, and replaced multiple listeners with a single one where possible.
Once I've done some more checking and tidying up and things I'll put something on git, if it's of interest to anyone.
Thanks for the tips,
Re: Struggling with speed - IE and the 'Stop running this scriptPosted: Thu Dec 03, 2009 3:35 pm
I'm glad you made some progress. And yes, you should share it with us. This is definitely an area with a lot of room for improvements, specially to create guidelines for the community.
|Page 1 of 1||[ 10 posts ]|
|You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum