Forum Moderators: open

Message Too Old, No Replies

puzzle bad performance in IE

         

bzgzd

3:58 am on Jan 5, 2011 (gmt 0)

10+ Year Member



Hi.

I would like to create web page with some puzzles (nurikabe) that could be solved in browser using JavaScript and to first test my limits I created this test page:

www.espordia.com/nurikabe/

What I need is 50x50 grid and when user clicks on any cell it changes its background.

My solution works good in all browsers I tested (Firefox, Chrome, Opera, Safari) except IE. When I click on cells faster, IE has big performance issues.

What I did is table with 50x50 cells and handling onmouseup events...

Do you have any tips how I could achieve this to be faster (in IE) ?

daveVk

6:34 am on Jan 5, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Each td creates an anon function for onmousedown event. That is a lot of functions, better to assign these in js, tdEl.onmousedown = se; and no anon functions will be involved.

Will it solve problem ?

bzgzd

8:41 am on Jan 5, 2011 (gmt 0)

10+ Year Member



Will it solve problem ?

Unfortunately not. I tried it also that way.
Actually I added those onmousedown functions to speed it up a little bit.

With se function I only tried to stop event bubbling:
function se(e)
{
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}


Version without onmousedown on td elements (and with 20 clicks test button):

www.espordia.com/nurikabe/test2.php

It seems that IE is simply very bad in performance... :-(
With 50x50 table on web page it takes me around 5 seconds to click a button 20 times. With FF or Chrome i can do it in 2.5 seconds and it feels like my clicking speed is limit and not browser javascript

bzgzd

9:17 am on Jan 5, 2011 (gmt 0)

10+ Year Member



There are two things that I found out:

1. If I make error in javascript in onmousedown for each td element IE works much faster
2. On bottom of table performance is better than on top...

This version with intent java script error is fastest on IE (still not even close to other browsers):

www.espordia.com/nurikabe/test3.php

daveVk

12:12 pm on Jan 5, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



function se possibly should return false; in addition or instead, that will cancel any default processing ( if there is any ).

Fotiman

4:10 pm on Jan 5, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




What I need is 50x50 grid and when user clicks on any cell it changes its background.

Rather than attaching 2500 event handlers, use just 1 event handler attached to a common ancestor (like the table), and let that delegate to the appropriate action.
For example:

var puzzle_table = document.getElementById('puzzle_table');
puzzle_table.onmousedown= function(event){
// do some cross browser normalization
event = event || window.event;
var target = event.target || event.srcElement;
// target is the element that triggered the event
// do whatever it is you want with it
};


And then remove all of those inline JavaScript event handlers, which:
1. Are a pain to manage
2. Add bloat to the HTML page
3. Don't promote a clean separation of content and behavior

bzgzd

12:53 am on Jan 6, 2011 (gmt 0)

10+ Year Member



Thank you very much for all help and effort, and also that code you emailed me. I will for sure use it.

I already uploaded it for testing to web-server: www.espordia.com/nurikabe/

However I am not very experienced with JavaScript. Can you please explain a little bit basics of that js code:

I mean that top function:
(function ()
{

var g_columns = 50, g_rows = 50;

...

puzzle_table.onmouseup = function(e)
{
// do some cross browser normalization
e = e || window.event;
var target = e.target || e.srcElement;
target.style.background = (e.button == 2 ? "red" : "blue");
};

})();

Does this function has no name? ...or no body? :-)
And what is the purpose of it?
And I don't understand all those parenthesis there...

Also I am generating that web page from php script and its content will be dependent on concrete puzzle.
That means puzzle dimensions are not always 50x50 so can I somehow pass arguments to that function to set those global variables?

---

I am sure that this way it is much better implemented, but still in IE speed is very poor.
Actually it is quite good using right-mouse button in bottom parts of table.

It seems that IE is doing some additional work with left mouse button clicks (which is not done after RMB click) and also for some reason changing cell background on top cells is slower than on bottom.

bzgzd

1:08 am on Jan 6, 2011 (gmt 0)

10+ Year Member



Making JavaScript error in onmousedown for each td element eliminates performance difference in IE between LMB and RMB clicks.
www.espordia.com/nurikabe/test3.php

And this performance increase can't be achieved by using cancelBubble. I believe the reason is bad implementation of canceling event bubble within IE.

And still there is difference between top and bottom part of table (even with table-layout: fixed)...

Fotiman

2:39 pm on Jan 6, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



That is called an "anonymous" function. It has no name.

function () {}

That is an anonymous function.

function () {}();

That is an anonymous function that is being called immediately. However, convention is to wrap the function definition in parenthesis as well so that you know that this is a function that is going to be executed immediately. So you end up with this:

(function () {})();

The purpose in this case is to create a function scope to store variables in so that the code doesn't contaminate the global scope with variables that might some day conflict with other libraries, etc. And since I want that code to execute immediately, putting it all in an anonymous function that executes immediately does the trick.


Also I am generating that web page from php script and its content will be dependent on concrete puzzle.
That means puzzle dimensions are not always 50x50 so can I somehow pass arguments to that function to set those global variables?


If we want to put the JavaScript in a separate file but still pass it some dynamic PHP-generated values, then there are a few options:

1. We could create a single global variable that contains an object. This acts as a sort of namespace. A good approach, but I don't think we need to go that route just yet.

2. You could keep the JavaScript in the PHP file and just use PHP where those variables are declared:

var g_columns = <?php echo cols; ?>;

But this doesn't support clean separation of content and behavior, so I don't like this option.


3. You could modify your server to run .js files through the PHP processor and then put the JavaScript code with some PHP (like #2) in the .js file. This is a better separation of layers, but I don't like the idea of having .js files running through the PHP processor, as that can affect (or be affected by) browser caching.


4. Modify the JavaScript code to determine the number of columns/rows from the DOM. This is the approach I would take. For example, you can determine the number of rows by counting the number of <tr> elements in the puzzle_table, and the number of columns by counting the number of <td> elements in the puzzle_table and then dividing that by the number of rows. For example:

g_rows = puzzle_table.getElementsByTagName('tr').length,
g_columns = puzzle_table.getElementsByTagName('td').length / g_rows;


This 4th option is the one I would chose. There are several ways to skin that cat, but this option allows you to keep the JavaScript in it's own file, and removes the need to pass any variables from PHP to JavaScript. :)


but still in IE speed is very poor.

Really? I found the speed to be nearly identical in IE7, Firefox 3.6, and Chrome. What version of IE are you using?

One thing you might try is setting the className on the TD instead of setting the background property of the style. For example:

//target.style.background = (e.button == 2 ? "red" : "blue");
target.className = (e.button == 2 ? "rmb" : "lmb");


Then in your CSS, add the following just after the #puzzle_table td rules:

#puzzle_table td.lmb { /* lmb = left mouse button */
background: blue;
}
#puzzle_table td.rmb { /* rmb = right mouse button */
background: red;
}


Generally speaking, setting the class name is slightly faster than setting properties of the style object.

bzgzd

10:04 pm on Jan 6, 2011 (gmt 0)

10+ Year Member



Thanks for those tips. I will for now use as you suggested number 4. to get number of rows and columns.

Something like this:
var g_rows = puzzle_table.rows.length;
var g_columns = (puzzle_table.rows[0]).cells.length;

Later I will need to use also 1. or 2. method because initial state of puzzle will be read from mysql table by php and that string I will need to use by JavaScript to fill-up two dimensional array with starting numbers accordingly and set starting cell backgrounds.

Really? I found the speed to be nearly identical in IE7, Firefox 3.6, and Chrome. What version of IE are you using?

This is interesting... I am using IE8 and by faster clicking performance in IE is much slower then in all other browsers. I tries it also on other PC with same results (but also IE8).

I recorded it on my PC here (first in FF and then in IE) www.youtube.com/watch?v=I8GrGwP8WkM:
[youtube.com...]

Fotiman

1:52 pm on Jan 7, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Wow, that is quite a delay. Very strange. I wonder if this is specific to IE8.

astupidname

5:18 am on Jan 8, 2011 (gmt 0)

10+ Year Member



This is an interesting test of browser performance, and not so much a javascript issue. The issue appears to be the browser's slow response to left mouse button. Excessive left mouse button clicking appears to just "pile up" in the browser (IE) until it is able to finish processing each one. It seems the performance (in IE) is much much better with the right mouse button than the left one. Very peculiar that there would be a difference between handling of left and right button, but I would say forget about it now as it's a browser limitation. At any rate, it would seem highly unlikely that this rate of clicking speed will be necessary for a puzzle. If you wish to build games with greater performance, perhaps flash would be much better choice anyhow.

bzgzd

6:42 am on Jan 8, 2011 (gmt 0)

10+ Year Member



I can confirm that in IE 7 this works fast enough.

I wanted to be sure it is not just some "malware" addon in my IE 8 so I downloaded from microsoft virtual hard disks with preinstalled IE7 and IE8 and on IE7 speed is ok but IE8 has those delays...

And I also added smaller table to that test page. So now it has 10x10 and also 50x50 on one page.
10x10 works fast also in IE8...

Clicking on 50x50 lags in IE8 and also other mouse activities are delayed, so for example scrolling page with mouse wheel after few fast clicks is performed only after all clicks are handled... but to me it seems they are handled one by one, just too slow.

bzgzd

2:51 pm on Jan 8, 2011 (gmt 0)

10+ Year Member



I found some solution to this IE8 delay...

One guy on msdn forum gave me tip to try IE quirks mode and it did solve the problem.

I added before doctype definition this comment:
<!-- This comment will put IE 6, 7, 8, and 9 in quirks mode -->

and after that speed in IE8 is also good.

I have no idea why, but probably it has something to do with IE8 different handling of table cell contents in quirks mode.

And I hope I will not run into some layout troubles or something when I will do real web page because of that quirks mode...

Fotiman

3:25 pm on Jan 8, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Yeah, I am never a fan of using Quirks mode. It might solve this particular problem, but may cause you bigger headaches down the road. I would keep looking for another solution. I wonder if using an Event Listener instead of Event Handler would show any different performance?