I am trying to improve performance of the select2 v3.4.8 library in IE8.
Essentially, I have narrowed the problem down to the call from the SingleSelect2's opening method to the parent AbstractSelect2's opening method. The method call I am speaking of is this one:
this.parent.opening.apply(this, arguments);
I have seen this call take upwards of 5 seconds to complete. In some instances, it has taken up to 10 seconds to open the dropdown in IE8.
I've made some performance improvements already. For example, rather than constantly adding the:
<div id="select2-drop-mask" class="select2-drop-mask"></div>
to the DOM programmatically, I just added it directly to the markup and set it's display:none. This saves quite a number of cycles because apparently, adding elements to the DOM in IE8 is expensive to do from Javascript.
But I still want to get more performance improvements than this. We have only increased performance by about 10-20% by making this change.
Does anyone have any suggestions for me?
We've already cached the data to display in the dropdown on the client on page load. So, there are zero server calls being made when the dropdown is opening. The performance bottleneck is entirely inside the select2 library itself.
Unfortunately, we are unable to upgrade our select2 library. Doing so would be at least an 8-Point User Story, so it's prohibitive at this time for us to undertake an upgrade.
Thanks to anyone who's able to help!
-classTemplateT
Related
This is largely a theoretical question, for which I do have a practical purpose. I first am looking for some conceptual answers before diving into practice, as perhaps the idea itself does not make sense.
Imagine a slideshow that is entirely javascript-based. Users see a large image on their screen and click to move to the next large image. Upon clicking, the next image is loaded and inserted into the DOM, replacing the previous one.
I recently learned that prefetching directives can help in speeding up the loading of resources that are very likely to be used next. Note that I said resources, not pages. The slideshow is a single page.
In an image slideshow, it is very obvious that it is likely that the next image is needed, thus if image1 is on screen, I could dynamically add this to the DOM:
<link rel="prefetch" href="http://img.mysite.com/img2.jpg">
My questions regarding this idea:
Would it work at all? Do browsers accept this directive when it is dynamically inserted in the DOM at run-time? Would it trigger the prefetch?
Is there a possibility of timing conflicts, where if prefetching would indeed work, it did not finish in time before the use does the "load" without prefetching? Obviously this can happen, but will it have unwanted side effects?
Will specific events such as image onload still work correctly, or are they never triggered in the case of a successful prefetch (assuming it works at all)?
I did a lot of searching but I am unable to find answers on this specific situation of dynamically injected prefetch hints.
onload always gets triggered, even if the image is coming from cache. You do not have to worry about timing effects or race conditions, any such behavior would be a browser bug.
As mentioned in comments, rel=prefetch is not the only way of achieving pre-fetching. It works though even when dynamically inserted into the DOM. After all, you could fetch the image without the prefetch attribute and hide it.
Showing then hiding animated indicator / spinner gifs are a good way to show a user that their action has worked and that something is happening while they wait for their action to complete - for example, if the action requires loading some data from a server(s) via AJAX.
My problem is, if the cause of the slowdown is a processor-intensive function, the gif freezes.
In most browsers, the GIF stops animating while the processor-hungry function executes. To a user, this looks like something has crashed or malfunctioned, when actually it's working.
JSBIN example
Note: the "This is slow" button will tie up the processor for a while - around 10 seconds for me, will vary depending on PC specs. You can change how much it does this with the "data-reps" attr in the HTML.
Expectation: On click, the animation runs. When the process is finished, the text changes (we'd normally hide the indicator too but the example is clearer if we leave it spinning).
Actual result: The animation starts running, then freezes until the process finishes. This gives the impression that something is broken (until it suddenly unexpectedly completes).
Is there any way to indicate that a process is running that doesn't freeze if JS is keeping the processor busy? If there's no way to have something animated, I'll resort to displaying then hiding a static text message saying Loading... or something similar, but something animated looks much more active.
If anyone is wondering why I'm using code that is processor-intensive rather than just avoiding the problem by optimising: It's a lot of necessarily complex rendering. The code is pretty efficient, but what it does is complex, so it's always going to be demanding on the processor. It only takes a few seconds, but that's long enough to frustrate a user, and there's plenty of research going back a long time to show that indicators are good for UX.
A second related problem with gif spinners for processor-heavy functions is that the spinner doesn't actually show until all the code in one synchronous set has run - meaning that it normally won't show the spinner until it's time to hide the spinner.
JSBIN example.
One easy fix I've found here (used in the other example above) is to wrap everything after showing the indicator in setTimeout( function(){ ... },50); with a very short interval, to make it asynchronous. This works (see first example above), but it's not very clean - I'm sure there's a better approach.
I'm sure there must be some standard approach to indicators for processor-intensive loading that I'm unaware of - or maybe it's normal to just use Loading... text with setTimeout? My searches have turned up nothing. I've read 6 or 7 questions about similar-sounding problems but they all turn out to be unrelated.
Edit Some great suggestions in the comments, here are a few more specifics of my exact issue:
The complex process involves processing big JSON data files (as in, JS data manipulation operations in memory after loading the files), and rendering SVG (through Raphael.js) visualisations including a complex, detailed zoomable world map, based on the results of the data processing from the JSON. So, some of it requires DOM manipulation, some doesn't.
I unfortunately do need to support IE8 BUT if necessary I can give IE8 / IE9 users a minimal fallback like Loading... text and give everyone else something modern.
Modern browsers now run CSS animations independently of the UI thread if the animation is implemented using a transform, rather than by changing properties. An article on this can be found at http://www.phpied.com/css-animations-off-the-ui-thread/.
For example, some of the CSS spinners at http://projects.lukehaas.me/css-loaders/ are implemented with transforms and will not freeze when the UI thread is busy (e.g., the last spinner on that page).
I've had similar problems in the past. Ultimately they've been fixed by optimizing or doing work in smaller chucks responding to user actions. In your case different zoom levels would trigger different rendering algorithms. You would only process what the user can see (plus maybe a buffer margin).
I believe the only simple workaround for you that would be cross-browser is to use setTimeout to give the ui thread a chance to run. Batch up your work into sets of operations and chain them together using several setTimeout calls. This will slow down the total processing time, but the user will at least be given feedback. Obviously this suggestion requires that your processing can be easily sectioned off. If that is the case you could also consider adding a progress bar for improved UX.
I made a nice website that does a lot of DOM manipulation. Works very nicely in chrome and firefox. Though the client has requested now that it also works in Internet Explorer. The latest version is good enough to start with (that would be 10.0.9200.16721 in my case).
So the adventure starts, i press F12 and see a set of pretty familiar developer tools (coming from chrome and firebug). As i'm tracking the JS code i notice that the HTML tab (with the DOM) doesn't actually update.
According to the manual here http://msdn.microsoft.com/en-us/library/ie/gg589512(v=vs.85).aspx it's "a good idea to refresh the HTML tab to get the current DOM, especially when you use dynamic elements." (d0h ??) problem is .. i can't find a button to enable automatic update of the HTML tab. So i would have to click the refresh button everytime i step into a new line of JS (never mind of real-time DOM view).
But that's not all ... every time i click the refresh button the whole DOM tree view collapses. And i have to click a bunch of pluses to view the node i'm interested in.
Does anyone have a solution for this? Because what would take days will take weeks this way...
Duplicate of How to inspect elements on dynamically created DOM by using IE developers tools
From doing a little digging aroung, it seems like this is an issue other people have reported too. This thread might be of some interest to you.
The most relevant part of it:
The problem is when you modify the dom (with or without jquery) from a callback which is called by a timeout, which is in a callback bound to an event, IE freaks out and doesn't update the dom tree in the development tool. Subsequent modifications to the changed tag in the dev tool won't have any effect.
According to my tests, it's the combination of that sequence of calls that make this happen. If the dom is modified from a settimeout callback but without being inside of an event callback, it works. If instead of settimeout you directly call a function that modifies the dom, it works.
Here's a working example of what you're saying to compound the issue.
Basically, this is an issue with IE. There is no fix available at the moment. The accepted answer on the other thread seems like a very poor workaround.
I have created a Drupal website that uses Openlayers to display maps. In one of these maps there are some "Filters" which the user can use to dynamically change the data shown in the map. The data are related to countries are shown as bubbles over the countries. The bubbles are drawn using Openlayers' API. A good amount of calculations go behind the scene while filters are selected. I have used setTimeout to avoid long running loops. The filters work fine. However, after a number of filters are clicked (e.g. if 12 filters are clicked), if the user tries to move to another page by clicking a link, in IE7 and IE8 the following error shows -
"Stop running this script?
A script on this page is causing your web browser to run slowly.
If it continues to run, your computer might become unresponsive."
This error does not show in any other browser and does not show in IE7, 8 until a link is clicked. Any pointer in this regard will be highly appreciated.
UPDATE : The problem was in OpenLayers' event cache. OpenLayers's clears the event cache in the window unload event and this was getting stuck in IE7 and IE8 (I am not sure why). So far I have been able to solve the issue when user clicks another link, by calling OpenLayers.Event.unloadCache() on click of normal links.
jQuery can be very resource expensive. The articles linked bellow gives you 10 good advices to perform better your jQuery applications. The most useful for me (I had the same problem a month ago) was to replace $.each() with traditional for lops and to replace extensive DOM construction with jquery templates. Also the use of ID instead of classes and to give a context for the selectors, selector caching, and so on.
This list is ordered using my own criteria of "usefulness" in the advices.
10 ways to instantly increase your jquery performance
improve your jquery 25 excellent tips
10 advanced jquery performance tuning tips from paul irish
8 jquery performance tips
You need to optimize your client script. Please refer to answers here.
Is there an easy way to save ajax requests into a browser's history so that when you use the back button it will preserve the last state of the DOM?
Websites like twitter and digg that use an ajax pager have a usability flaw where if you click next page several times then click away from the site and then return using the back button, you lose your place in the viewport since the DOM is restored to the first initial request.
I noticed safari actually preserves the dom after a few ajax requests on some sites.
Here is an example, Goto http://13gb.com, Click next a few times then click on an image and then click your back button. On webkit it preserved the last DOM state, but on gecko and ie it does not.
What would be the easiest way to replicate this functionality on other browsers?
I'm not the first person to tackle
this type of problem. I've drawn
inspiration and know-how from several
places to get this up and running:
The original bookmark/back button fix,
as used by Flash developers for a
little while now:
http://robertpenner.com/experiments/backbutton/flashpage.html
I've not actually looked at how they
implemented their solution but this is
where I got the idea for replacing
Robert Penner's frames with iframes:
http://dojotoolkit.org/intro_to_dojo_io.html#so-about-that-thorny-back-button
Rich Rutter's use of the hash for
bookmarking:
http://clagnut.com/sandbox/slideshow.html#5
For this little experiment I've used Harry Fuecks' JPSpan
It's a fantastic framework that makes the methods you define in your server-side PHP classes available to your Javascript via XmlHttpRequest.
It's the simplest way I've come across
to get started with AJAX. I had the
guts of my demo up and running in
about 10 minutes! I'm using
Algorithm's Timer object:
http://codingforums.com/archive/index.php/t-10531.html
And Scott Andrew's cross-browser event
handler:
http://scottandrew.com/weblog/articles/cbs-events
Source: http://www.contentwithstyle.co.uk/content/fixing-the-back-button-and-enabling-bookmarking-for-ajax-apps
For jQuery:
https://stackoverflow.com/questions/116446/what-is-the-best-back-button-jquery-plugin
You may be interested in the jQuery History plugin:
http://tkyk.github.com/jquery-history-plugin/