Maian
07-13-2005, 12:58 PM
I posted this in reply to this blog post (http://blog.codingforums.com/index.php/main/blogentry/reducing_code_forking_in_event_handlers/). I'm hoping to get some discussion on this issue here:
I've thought about using HTCs to bring IE up to spec, but I've heard that they have couple performance issues.
1) IE erroneously re-requests the .htc for every bound element. There is a server-side workaround involving setting the expiration header of the .htc, but no client-side solution.
http://slingfive.com/pages/code/xDOM/ (see notes section)
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q319176
2) It seems like the .htc - or the script inside the .htc - has to be parsed every time an element is bound. IE creates an additional JScript engine for the .htc instead of using the main one. I don't know if it creates the JScript engine for every bound element instead of sharing it for all bound elements, but if it did, that would be even worse.
http://blogs.msdn.com/ericlippert/archive/2004/02/04/67525.aspx
Articles talking about the performance of csshover.htc (http://www.xs4all.nl/~peterned/csshover.html):
http://www.aplus.co.yu/adxmenu/csshoverhtc-and-ie-freeze/
http://www.aplus.co.yu/adxmenu/end-of-the-road/
http://www.activewidgets.com/javascript.forum.5490.4/grid-containing-page-frozen-for.html
(and more)
(note: I'm not sure if its the HTC aspect of it being slow or the script itself, since the HTC is applied only to the body element)
3) They can cause a memory leak until the page is refreshed or directed to another page. Specifically, IE doesn't deallocate memory when a behavior is dynamically removed, which means it can happen when the bound element is removed. Thus, pages that are dynamically changed a lot will start hogging up more and more memory.
From http://msdn.microsoft.com/workshop/author/behaviors/howto/using.asp:
Note A behavior attached to an element through CSS, using a style rule defined in the document, is automatically detached from the element as soon as the element is removed from the document tree. Once the element is removed, all associations of that element to any element in the document tree, such as style sheet rules that specify behaviors, are stripped from the element as well. On the other hand, a behavior attached to an element through an inline style, or through the addBehavior method, is not automatically detached from the element when the element is removed from the document hierarchy. These two methods of applying behaviors have no dependencies on the containing document, and therefore the behavior remains applied to the element even as it is removed from the document tree. The removeBehavior method can be invoked to explicitly detach this type of behavior from the element.
The only "fix" is outside the control of the developer - the user has to edit his/her registry.
http://dotnetjunkies.com/WebLog/kmotion/archive/2004/12/08/35627.aspx
http://support.microsoft.com/?id=309170
Then I tried this Element prototyping HTC (http://blog.codingforums.com/index.php/main/blogentry/element_prototyping_in_internet_explorer_55_and_above/) on a page with ~500 elements in the body. I'm using Tomcat on top of Apache with the default config, plus
# set IE .htc expiration to 1 day
ExpiresActive On
AddType text/x-component .htc
ExpiresByType text/x-component A86400
to fix issue 1. On this 1.6Ghz Pentium M laptop, the page took ~1.5 seconds to load (and reload) and during that time IE was unresponsive.
Another test: I saved this page (newthread.php) as an htm, which has around 650 elements in the body, added the behavior code, and loaded (and reloaded) it up in IE: took ~3 seconds to load.
Then I tested a much lighter HTC: DOM2 event support (http://blog.codingforums.com/index.php/main/blogentry/reducing_code_forking_in_event_handlers/) on the same page (newthread.php). With the HTC: ~600ms. Without the HTC: ~250ms. That's more reasonable, but still bad.
During all this testing, I noticed another large problem: unloading the page takes much much longer and the browser is also unresponsive around this time. For newthread.php and the DOM2 support HTC, it took around 1 sec to unload. Unfortunately, this lag occurs after the window unload event, so I couldn't accurately time it.
Now I test it on a copy of the JavaScript forum listing (forumdisplay.php), which has around 1100 elements in the body. With the DOM2 support HTC: ~800ms to load, ~3 secs to unload. Without the HTC: ~420ms to load, nearly instantaneous unload.
So is there any way to improve the performance of HTCs, especially when applied to many elements?
I've thought about using HTCs to bring IE up to spec, but I've heard that they have couple performance issues.
1) IE erroneously re-requests the .htc for every bound element. There is a server-side workaround involving setting the expiration header of the .htc, but no client-side solution.
http://slingfive.com/pages/code/xDOM/ (see notes section)
http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q319176
2) It seems like the .htc - or the script inside the .htc - has to be parsed every time an element is bound. IE creates an additional JScript engine for the .htc instead of using the main one. I don't know if it creates the JScript engine for every bound element instead of sharing it for all bound elements, but if it did, that would be even worse.
http://blogs.msdn.com/ericlippert/archive/2004/02/04/67525.aspx
Articles talking about the performance of csshover.htc (http://www.xs4all.nl/~peterned/csshover.html):
http://www.aplus.co.yu/adxmenu/csshoverhtc-and-ie-freeze/
http://www.aplus.co.yu/adxmenu/end-of-the-road/
http://www.activewidgets.com/javascript.forum.5490.4/grid-containing-page-frozen-for.html
(and more)
(note: I'm not sure if its the HTC aspect of it being slow or the script itself, since the HTC is applied only to the body element)
3) They can cause a memory leak until the page is refreshed or directed to another page. Specifically, IE doesn't deallocate memory when a behavior is dynamically removed, which means it can happen when the bound element is removed. Thus, pages that are dynamically changed a lot will start hogging up more and more memory.
From http://msdn.microsoft.com/workshop/author/behaviors/howto/using.asp:
Note A behavior attached to an element through CSS, using a style rule defined in the document, is automatically detached from the element as soon as the element is removed from the document tree. Once the element is removed, all associations of that element to any element in the document tree, such as style sheet rules that specify behaviors, are stripped from the element as well. On the other hand, a behavior attached to an element through an inline style, or through the addBehavior method, is not automatically detached from the element when the element is removed from the document hierarchy. These two methods of applying behaviors have no dependencies on the containing document, and therefore the behavior remains applied to the element even as it is removed from the document tree. The removeBehavior method can be invoked to explicitly detach this type of behavior from the element.
The only "fix" is outside the control of the developer - the user has to edit his/her registry.
http://dotnetjunkies.com/WebLog/kmotion/archive/2004/12/08/35627.aspx
http://support.microsoft.com/?id=309170
Then I tried this Element prototyping HTC (http://blog.codingforums.com/index.php/main/blogentry/element_prototyping_in_internet_explorer_55_and_above/) on a page with ~500 elements in the body. I'm using Tomcat on top of Apache with the default config, plus
# set IE .htc expiration to 1 day
ExpiresActive On
AddType text/x-component .htc
ExpiresByType text/x-component A86400
to fix issue 1. On this 1.6Ghz Pentium M laptop, the page took ~1.5 seconds to load (and reload) and during that time IE was unresponsive.
Another test: I saved this page (newthread.php) as an htm, which has around 650 elements in the body, added the behavior code, and loaded (and reloaded) it up in IE: took ~3 seconds to load.
Then I tested a much lighter HTC: DOM2 event support (http://blog.codingforums.com/index.php/main/blogentry/reducing_code_forking_in_event_handlers/) on the same page (newthread.php). With the HTC: ~600ms. Without the HTC: ~250ms. That's more reasonable, but still bad.
During all this testing, I noticed another large problem: unloading the page takes much much longer and the browser is also unresponsive around this time. For newthread.php and the DOM2 support HTC, it took around 1 sec to unload. Unfortunately, this lag occurs after the window unload event, so I couldn't accurately time it.
Now I test it on a copy of the JavaScript forum listing (forumdisplay.php), which has around 1100 elements in the body. With the DOM2 support HTC: ~800ms to load, ~3 secs to unload. Without the HTC: ~420ms to load, nearly instantaneous unload.
So is there any way to improve the performance of HTCs, especially when applied to many elements?