Hi I''ve tried to use Prototype as a base for few large intranet applications I''m working on. Unfortunately I encountered some serious performance problems when working with Internet Explorer. It''s really sluggish when it comes to DOM operations and Prototype could really benefit from some small optimizations. I created a testase to show a difference between my optimized and standard versions of library. See for yourself: http://szafranek.net/_misc/prototype/standard.html http://szafranek.net/_misc/prototype/optimized.html The problem I''m having is to get these fixes (http://szafranek.net/_misc/prototype/j/prototype1.4-opt.js) into the official Prototype release. I send a darcs patch to Sam few weeks ago, yet it didn''t went into latest release; Sam also doesn''t answer to email. The changes are really small and don''t affect the API at all, so there shouldn''t be any problem. This performance issues really hurt the apps I''m working on, so currently I maintain my own branch of Prototype, with these custom optimizations. Could any of the existing Prototype contributors help to add these fixes to official release? Maybe you could convince Sam :). I think that would really benefit everybody who uses the library in medium and large applications and has to take IE into account. Thanks -- Krzysztof Szafranek http://szafranek.net Krzysztof Szafranek http://szafranek.net
Wow, that is some major difference! I know nothing about Sam''s plans or how to get any of this into the official branch, but before I copy your version into my project, would you mind explaining briefly the things you changed? Thank you. -Ryan Gahl -----Original Message----- From: rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org [mailto:rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of "Krzysztof Szafranek" Sent: Tuesday, December 20, 2005 9:26 AM To: rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: [Rails-spinoffs] Performance issues with Prototype Hi I''ve tried to use Prototype as a base for few large intranet applications I''m working on. Unfortunately I encountered some serious performance problems when working with Internet Explorer. It''s really sluggish when it comes to DOM operations and Prototype could really benefit from some small optimizations. I created a testase to show a difference between my optimized and standard versions of library. See for yourself: http://szafranek.net/_misc/prototype/standard.html http://szafranek.net/_misc/prototype/optimized.html The problem I''m having is to get these fixes (http://szafranek.net/_misc/prototype/j/prototype1.4-opt.js) into the official Prototype release. I send a darcs patch to Sam few weeks ago, yet it didn''t went into latest release; Sam also doesn''t answer to email. The changes are really small and don''t affect the API at all, so there shouldn''t be any problem. This performance issues really hurt the apps I''m working on, so currently I maintain my own branch of Prototype, with these custom optimizations. Could any of the existing Prototype contributors help to add these fixes to official release? Maybe you could convince Sam :). I think that would really benefit everybody who uses the library in medium and large applications and has to take IE into account. Thanks -- Krzysztof Szafranek http://szafranek.net Krzysztof Szafranek http://szafranek.net _______________________________________________ Rails-spinoffs mailing list Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs The information transmitted in this electronic mail is intended only for the person or entity to which it is addressed and may contain confidential, proprietary, and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from all computers.
On 12/20/05, Ryan Gahl <Ryan.Gahl-nlycWCgr5/vuufBYgWm87A@public.gmane.org> wrote:> Wow, that is some major difference! I know nothing about Sam''s plans or > how to get any of this into the official branch, but before I copy your > version into my project, would you mind explaining briefly the things > you changed? > Thank you. > > -Ryan Gahl >------8<------------------------ %> diff prototype.js prototype1.4-opt.js 401c401,402 < for (var i = 0; i < iterable.length; i++) ---> var len = iterable.length; > for (var i = 0; i < len; i++)413c414,415 < for (var i = 0; i < this.length; i++) ---> var len = this.length; > for (var i = 0; i < len; i++)451c453,454 < for (var i = 0; i < this.length; i++) ---> var len = this.length; > for (var i = 0; i < len; i++)837c840,841 < if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) ---> var re = new RegExp("(^|\\s)" + className + "(\\s|$)"); > if (child.className.match(re))------8<------------------------ That''s all ! It''s amazing to see that how 3 little optimizations can improve performance! Krzysztof, I hope that your patch will be integrated soon because it is really usefull... 8) Thanks, Nicolas Terray
Ok, how do those optimize anything? Is it some bug in IE? He''s just copying a value to a local variable and using that instead and there''s a big speed difference? What the heck? I could understand if .length were a function, and had to recalculate the value each time, but it''s just an attribute. That''s just odd to me. I wonder if most of the optimization comes from the RegExp object part. Greg> -----Original Message----- > From: rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org[mailto:rails-spinoffs-> bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of Nicolas Terray > Sent: Tuesday, December 20, 2005 8:45 AM > To: rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > Subject: Re: [Rails-spinoffs] Performance issues with Prototype > > On 12/20/05, Ryan Gahl <Ryan.Gahl-nlycWCgr5/vuufBYgWm87A@public.gmane.org> wrote: > > Wow, that is some major difference! I know nothing about Sam''s plansor> > how to get any of this into the official branch, but before I copyyour> > version into my project, would you mind explaining briefly thethings> > you changed? > > Thank you. > > > > -Ryan Gahl > > > > ------8<------------------------ > %> diff prototype.js prototype1.4-opt.js > 401c401,402 > < for (var i = 0; i < iterable.length; i++) > --- > > var len = iterable.length; > > for (var i = 0; i < len; i++) > 413c414,415 > < for (var i = 0; i < this.length; i++) > --- > > var len = this.length; > > for (var i = 0; i < len; i++) > 451c453,454 > < for (var i = 0; i < this.length; i++) > --- > > var len = this.length; > > for (var i = 0; i < len; i++) > 837c840,841 > < if (child.className.match(new RegExp("(^|\\s)" + className + > "(\\s|$)"))) > --- > > var re = new RegExp("(^|\\s)" + className + "(\\s|$)"); > > if (child.className.match(re)) > ------8<------------------------ > > That''s all ! > > > It''s amazing to see that how 3 little optimizations can improve > performance! > Krzysztof, I hope that your patch will be integrated soon because it > is really usefull... > 8) > > Thanks, > Nicolas Terray > _______________________________________________ > Rails-spinoffs mailing list > Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs
It just looks like an attribute to the programmer, but the implementation underneath could very well be iterating the whole array each time. There''s no way to know. On 12/20/05, Gregory Hill <Gregory_Hill-l9nu40+TWxQ@public.gmane.org> wrote:> > Ok, how do those optimize anything? Is it some bug in IE? He''s just > copying a value to a local variable and using that instead and there''s a > big speed difference? What the heck? I could understand if .length > were a function, and had to recalculate the value each time, but it''s > just an attribute. That''s just odd to me. I wonder if most of the > optimization comes from the RegExp object part. > > Greg > > > -----Original Message----- > > From: rails-spinoffs-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > [mailto:rails-spinoffs- > > bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of Nicolas Terray > > Sent: Tuesday, December 20, 2005 8:45 AM > > To: rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > > Subject: Re: [Rails-spinoffs] Performance issues with Prototype > > > > On 12/20/05, Ryan Gahl <Ryan.Gahl-nlycWCgr5/vuufBYgWm87A@public.gmane.org> wrote: > > > Wow, that is some major difference! I know nothing about Sam''s plans > or > > > how to get any of this into the official branch, but before I copy > your > > > version into my project, would you mind explaining briefly the > things > > > you changed? > > > Thank you. > > > > > > -Ryan Gahl > > > > > > > ------8<------------------------ > > %> diff prototype.js prototype1.4-opt.js > > 401c401,402 > > < for (var i = 0; i < iterable.length; i++) > > --- > > > var len = iterable.length; > > > for (var i = 0; i < len; i++) > > 413c414,415 > > < for (var i = 0; i < this.length; i++) > > --- > > > var len = this.length; > > > for (var i = 0; i < len; i++) > > 451c453,454 > > < for (var i = 0; i < this.length; i++) > > --- > > > var len = this.length; > > > for (var i = 0; i < len; i++) > > 837c840,841 > > < if (child.className.match(new RegExp("(^|\\s)" + className + > > "(\\s|$)"))) > > --- > > > var re = new RegExp("(^|\\s)" + className + "(\\s|$)"); > > > if (child.className.match(re)) > > ------8<------------------------ > > > > That''s all ! > > > > > > It''s amazing to see that how 3 little optimizations can improve > > performance! > > Krzysztof, I hope that your patch will be integrated soon because it > > is really usefull... > > 8) > > > > Thanks, > > Nicolas Terray > > _______________________________________________ > > Rails-spinoffs mailing list > > Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > > http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs > _______________________________________________ > Rails-spinoffs mailing list > Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs >_______________________________________________ Rails-spinoffs mailing list Rails-spinoffs-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs
Although IE performace is really BAD, computing length each time isn''t a bug. This property behaves exactly as a method, it''s computed each time the loop is executed. Most of the performance gain is from it, not from RegExp handling. Imagine the situation, when loop body removes one element from the array. It''s quite common situation, for example when you operate on select tag and remove options dynamically in loop body, in each loop pass. Thus the length of option collection has changed, and the length must be recalculated. It seems to me like a Uniform Access Principle done in JavaScript way :).> Ok, how do those optimize anything? Is it some bug in IE? > He''s just > copying a value to a local variable and using that instead > and there''s a big speed difference? > What the heck? I could understand if .length > were a function, and had to recalculate the value each time, > but it''s just an attribute. > That''s just odd to me. I wonder if most of the > optimization comes from the RegExp object part.> GregKrzysztof Szafranek http://szafranek.net
> Imagine the situation, when loop body removes one element from the > array. It''s quite common situation, for example when you operate on > select tag and remove options dynamically in loop body, in each loop > pass. Thus the length of option collection has changed, and the > length must be recalculated.It makes sense, but I was curious how it is possible, given the fact that in Javascript when you access something as an attribute, it doesn''t behave as a function. For example, say you were to create your own object with a .length attribute. Could you recalculate that on the fly? No, unless you defined it as a function and then you''d have to call it as a function (this.length() instead of this.length). (Or is it possible by some means I am unaware of?) So, changing the behavior for built-ins opens up a large can of worms for programming errors. When you call array.length, you expect it to just retrieve a value. If it were a function, array.length(), you''d expect it to be more intensive and you would be more likely to store the value locally. It''s inconsistent, and troublesome, given the fact that there could be myriad other similar examples. Anyway, I guess it just annoys me that this is possible because it means I probably have a lot of optimizing I could do that wouldn''t have been an issue if they''d made the built-ins behave the same as user-defined objects. Regardless, thanks for bringing it to light; I would''ve never known otherwise. Greg
Gregory Hill wrote:>>Imagine the situation, when loop body removes one element from the >>array. It''s quite common situation, for example when you operate on >>select tag and remove options dynamically in loop body, in each loop >>pass. Thus the length of option collection has changed, and the >>length must be recalculated. > > > It makes sense, but I was curious how it is possible, given the fact > that in Javascript when you access something as an attribute, it doesn''t > behave as a function. For example, say you were to create your own > object with a .length attribute. Could you recalculate that on the fly? > No, unless you defined it as a function and then you''d have to call it > as a function (this.length() instead of this.length). (Or is it > possible by some means I am unaware of?)In may programming languages there is a concept of getters and setters, that are functions that run when a "property" is accessed or set. The length property of an Array object is an example of a getter. Pretty sure that it''s not cross browser compatible (not IE, but FF1.5 in my testing), but actually you can define getters and setters that behave within your code as if they are properties, but they are actually functions/methods. Here''s a quick page that describes this concept a little: http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Creating_New_Objects:Defining_Getters_and_Setters and also a little more here: http://ajaxian.com/archives/2005/11/getters_and_set.html Probably more link via google> So, changing the behavior for > built-ins opens up a large can of worms for programming errors. When > you call array.length, you expect it to just retrieve a value. If it > were a function, array.length(), you''d expect it to be more intensive > and you would be more likely to store the value locally. It''s > inconsistent, and troublesome, given the fact that there could be myriad > other similar examples. Anyway, I guess it just annoys me that this is > possible because it means I probably have a lot of optimizing I could do > that wouldn''t have been an issue if they''d made the built-ins behave the > same as user-defined objects.Anytime you access a variable''s property multiple times, as in a for loop it takes longer to access it via obj.property then to use var p = obj.property and then use p wherever you needed the value. This presumes that the value of p doesn''t change over the course of the operations you''re performing, or you need to "recalculate" it every time you change it, or just access the property directly each time and live with the extra time it takes. -- Danilo Celic | Extending Knowledge Daily : http://CommunityMX.com/ | Team Macromedia for Dreamweaver : http://macromedia.com/go/team/
On 20/12/05, Gregory Hill <Gregory_Hill-l9nu40+TWxQ@public.gmane.org> wrote:> He''s just > copying a value to a local variable and using that instead and there''s a > big speed difference?"foo.bar" or even "foo.bar.baz.qwertz" are more expensive to lookup than "temp". So if you have to use the former multiple times (e.g. in a loop), it is faster to create a local variable to make the long lookup only once.> I could understand if .length > were a function, and had to recalculate the value each time, but it''s > just an attribute.Depends. There is another effect here. The array could really be not an array, but an NodeList (like element.childNodes or a list returned by document.getElementsByTagName() ). See http://www.w3.org/TR/DOM-Level-2-Core/ NodeLists are live. That is: If you have var t = element.childNodes and you remove a child from the element by using element.removeChild(), t will follow this change. So any lookup into a NodeList is quite expensive, as the DOM is involved. So indeed, .length has to be calculated on each access (The JS engine of the browser might remedy this through caching - See quirksmode.org for performance comparisions regarding DOM access/manipulation). A nice prototype.js way to create an regular Array of nodes from a NodeList is var arr = $A(nodelist)
On 20/12/05, Nicolas Terray <nicolas.terray-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> 837c840,841 > < if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) > --- > > var re = new RegExp("(^|\\s)" + className + "(\\s|$)"); > > if (child.className.match(re))One can even put the var re=... one line higher, outside the inject() iteration, so it is created only once.