I''ve noticed that the performance of my web apps is very slow when dealing with large amounts of data (e.g. generating >100 tree nodes, each of which includes InPlaceEditors, Tooltips (my own using Prototype/SAU), lots of various nodes built with Builder.node, etc...). I started using the new Firebug 1.0 beta''s profiling and discovered a few things. 1) Builder.node calls escapeHTML on all attribute values when parsing the attributes 2) escapeHTML creates a div node and a text node each time it is called 3) The combination of 1) and 2) yields a massive performance hit So what is the reason for 1)? I don''t know of any *standard* attribute values offhand that use special HTML characters, nor can I think of a good reason to. I don''t think it''d be too much to ask for the programmer to realize when he may be using HTML characters and have the foresight to add .escapeHTML to the string when it is passed. Maybe there is a common case that makes this worth while that I don''t know of? ------------For reference---------- _attributes: function(attributes) { var attrs = []; for(attribute in attributes) attrs.push((attribute==''className'' ? ''class'' : attribute) + ''="'' + attributes[attribute].toString().escapeHTML() + ''"''); return attrs.join(" "); }, ----------------------------------- On 2), why can''t the escapeHTML function create a div node and a text node once one the first call and reuse it on subsequent calls? Also, is this not a leak? ------------For reference--------- escapeHTML: function() { var div = document.createElement(''div''); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, ---------------------------------- Thoughts? Thanks, Colin --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Am 04.01.2007 um 13:19 schrieb Colin Mollenhour:> On 2), why can''t the escapeHTML function create a div node and a > text node once one the first call and reuse it on subsequent > calls? Also, is this not a leak? > ------------For reference--------- > escapeHTML: function() { > var div = document.createElement(''div''); > var text = document.createTextNode(this); > div.appendChild(text); > return div.innerHTML; > }, > ----------------------------------That''s something we''d need to measure. The text node creation wouldn''t go away, and reusing the div node would mean to empty it out before adding the text node. I don''t really think that it would make a real difference. Best, Thomas --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Thomas Fuchs wrote:> Am 04.01.2007 um 13:19 schrieb Colin Mollenhour: >> On 2), why can''t the escapeHTML function create a div node and a text >> node once one the first call and reuse it on subsequent calls? Also, >> is this not a leak?a) this is veeeery browser dependent :( b) leak? can''t see a reason why.> > That''s something we''d need to measure.Let''s measure. Note that I threw in two more "old school" methods (string manipulation based). Browser: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20061222 Firefox/2.0.0.1 Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, String.split... Prototype: 2.829s @ 3535/s (n=10000) Prototype-oneDiv: 3.795s @ 2635/s (n=10000) String.replace: 0.640s @ 15625/s (n=10000) String.split: 1.303s @ 7675/s (n=10000) Rate Prototype-oneDiv Prototype String.split String.replace Prototype-oneDiv 2635/s -- -25% -66% -83% Prototype 3535/s 34% -- -54% -77% String.split 7675/s 191% 117% -- -51% String.replace 15625/s 493% 342% 104% -- Tests duration: 8.567 seconds. Total duration: 13.127 seconds. Browser: Opera/9.10 (X11; Linux i686; U; en) Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, String.split... Prototype: 0.554s @ 18051/s (n=10000) Prototype-oneDiv: 0.569s @ 17575/s (n=10000) String.replace: 1.082s @ 9242/s (n=10000) String.split: 0.355s @ 28169/s (n=10000) Rate String.replace Prototype-oneDiv Prototype String.split String.replace 9242/s -- -47% -49% -67% Prototype-oneDiv 17575/s 90% -- -3% -38% Prototype 18051/s 95% 3% -- -36% String.split 28169/s 205% 60% 56% -- Tests duration: 2.560 seconds. Total duration: 6.118 seconds. Browser: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; FDM) Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, String.split... Prototype: 2.296s @ 4355/s (n=10000) Prototype-oneDiv: 1.889s @ 5294/s (n=10000) String.replace: 0.626s @ 15974/s (n=10000) String.split: 1.110s @ 9009/s (n=10000) Rate Prototype Prototype-oneDiv String.split String.replace Prototype 4355/s -- -18% -52% -73% Prototype-oneDiv 5294/s 22% -- -41% -67% String.split 9009/s 107% 70% -- -44% String.replace 15974/s 267% 202% 77% -- Tests duration: 5.921 seconds. Total duration: 10.234 seconds. Browser: Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, String.split... Prototype: 2.324s @ 4303/s (n=10000) Prototype-oneDiv: 1.761s @ 5679/s (n=10000) String.replace: 0.492s @ 20325/s (n=10000) String.split: 1.350s @ 7407/s (n=10000) Rate Prototype Prototype-oneDiv String.split String.replace Prototype 4303/s -- -24% -42% -79% Prototype-oneDiv 5679/s 32% -- -23% -72% String.split 7407/s 72% 30% -- -64% String.replace 20325/s 372% 258% 174% -- Tests duration: 5.927 seconds. Total duration: 10.194 seconds. Browser: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) Timing 10000 iterations of Prototype-oneDiv, Prototype, String.replace, String.split... Prototype-oneDiv: 2.457s @ 4070/s (n=10000) Prototype: 2.545s @ 3929/s (n=10000) String.replace: 2.732s @ 3660/s (n=10000) String.split: 2.557s @ 3911/s (n=10000) Rate String.replace String.split Prototype Prototype-oneDiv String.replace 3660/s -- -6% -7% -10% String.split 3911/s 7% -- -0% -4% Prototype 3929/s 7% 0% -- -3% Prototype-oneDiv 4070/s 11% 4% 4% -- Tests duration: 10.291 seconds. Total duration: 32.202 seconds. Test it yourself using your own system/browser: http://gfx.neohub.com/benchmark/t/escapeHTML.html cheers - -- Marius Feraru -----BEGIN PGP SIGNATURE----- iD8DBQFFnlrqtZHp/AYZiNkRAsISAJwNZn6KHQA8Cz64R1xieZjL+unUaQCgsTRI o1u0l0bFW2stZOZaEFlAfdU=Vkpv -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Marius Feraru a crit :> Browser: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) > Gecko/20061222 Firefox/2.0.0.1...> Tests duration: 8.567 seconds. > Total duration: 13.127 seconds.Great page, Marius, but I find oddly faster results in my Firefox 2 (Iceweasel branded, I run Debian): Browser: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/20061024 Iceweasel/2.0 (Debian-2.0+dfsg-1) Timing 1000 iterations of Prototype, Prototype-oneDiv, String.replace, String.split... Prototype: 0.162s @ 6173/s (n=1000) Prototype-oneDiv: 0.219s @ 4566/s (n=1000) String.replace: 0.042s @ 23810/s (n=1000) String.split: 0.135s @ 7407/s (n=1000) ... Tests duration: 0.558 seconds. Total duration: 3.720 seconds. Granted, this is not exactly your version (I use 20061024), but it''s 4+ times faster, with performance comparable to your Opera''s. Weird! -- Christophe Porteneuve a.k.a. TDD "[They] did not know it was impossible, so they did it." --Mark Twain Email: tdd-x+CfDp/qHev2eFz/2MeuCQ@public.gmane.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Great page, that is a cool utility that I''m sure I will use in the future! You''ve shown the "old school" methods are clearly faster for the top browsers (FF,IE6/7) which I think would make the change to String.replace or String.split worthwhile. (I was able to reproduce your results, only mine were a lot faster across the board, what CPU are you using?) Even though String.replace is slower in Opera I''d be in favor of it since Opera clearly has some room for improvement with that function so I''m guessing this may be improved in the future. Thanks, Colin Marius Feraru wrote:> > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Thomas Fuchs wrote: >> Am 04.01.2007 um 13:19 schrieb Colin Mollenhour: >>> On 2), why can''t the escapeHTML function create a div node and a text >>> node once one the first call and reuse it on subsequent calls? Also, >>> is this not a leak? > a) this is veeeery browser dependent :( > b) leak? can''t see a reason why. > >> >> That''s something we''d need to measure. > Let''s measure. Note that I threw in two more "old school" methods > (string manipulation based). > > > Browser: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) > Gecko/20061222 Firefox/2.0.0.1 > Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, > String.split... > Prototype: 2.829s @ 3535/s (n=10000) > Prototype-oneDiv: 3.795s @ 2635/s (n=10000) > String.replace: 0.640s @ 15625/s (n=10000) > String.split: 1.303s @ 7675/s (n=10000) > Rate Prototype-oneDiv Prototype String.split > String.replace > Prototype-oneDiv 2635/s -- -25% -66% > -83% > Prototype 3535/s 34% -- -54% > -77% > String.split 7675/s 191% 117% -- > -51% > String.replace 15625/s 493% 342% 104% > -- > Tests duration: 8.567 seconds. > Total duration: 13.127 seconds. > > > Browser: Opera/9.10 (X11; Linux i686; U; en) > Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, > String.split... > Prototype: 0.554s @ 18051/s (n=10000) > Prototype-oneDiv: 0.569s @ 17575/s (n=10000) > String.replace: 1.082s @ 9242/s (n=10000) > String.split: 0.355s @ 28169/s (n=10000) > Rate String.replace Prototype-oneDiv Prototype > String.split > String.replace 9242/s -- -47% -49% > -67% > Prototype-oneDiv 17575/s 90% -- -3% > -38% > Prototype 18051/s 95% 3% -- > -36% > String.split 28169/s 205% 60% 56% > -- > Tests duration: 2.560 seconds. > Total duration: 6.118 seconds. > > > Browser: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR > 2.0.50727; FDM) > Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, > String.split... > Prototype: 2.296s @ 4355/s (n=10000) > Prototype-oneDiv: 1.889s @ 5294/s (n=10000) > String.replace: 0.626s @ 15974/s (n=10000) > String.split: 1.110s @ 9009/s (n=10000) > Rate Prototype Prototype-oneDiv String.split > String.replace > Prototype 4355/s -- -18% -52% > -73% > Prototype-oneDiv 5294/s 22% -- -41% > -67% > String.split 9009/s 107% 70% -- > -44% > String.replace 15974/s 267% 202% 77% > -- > Tests duration: 5.921 seconds. > Total duration: 10.234 seconds. > > > Browser: Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) > Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, > String.split... > Prototype: 2.324s @ 4303/s (n=10000) > Prototype-oneDiv: 1.761s @ 5679/s (n=10000) > String.replace: 0.492s @ 20325/s (n=10000) > String.split: 1.350s @ 7407/s (n=10000) > Rate Prototype Prototype-oneDiv String.split > String.replace > Prototype 4303/s -- -24% -42% > -79% > Prototype-oneDiv 5679/s 32% -- -23% > -72% > String.split 7407/s 72% 30% -- > -64% > String.replace 20325/s 372% 258% 174% > -- > Tests duration: 5.927 seconds. > Total duration: 10.194 seconds. > > > Browser: Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 > (like Gecko) > Timing 10000 iterations of Prototype-oneDiv, Prototype, String.replace, > String.split... > Prototype-oneDiv: 2.457s @ 4070/s (n=10000) > Prototype: 2.545s @ 3929/s (n=10000) > String.replace: 2.732s @ 3660/s (n=10000) > String.split: 2.557s @ 3911/s (n=10000) > Rate String.replace String.split Prototype > Prototype-oneDiv > String.replace 3660/s -- -6% -7% > -10% > String.split 3911/s 7% -- -0% > -4% > Prototype 3929/s 7% 0% -- > -3% > Prototype-oneDiv 4070/s 11% 4% 4% > -- > Tests duration: 10.291 seconds. > Total duration: 32.202 seconds. > > > Test it yourself using your own system/browser: > http://gfx.neohub.com/benchmark/t/escapeHTML.html > > cheers > - -- > Marius Feraru > -----BEGIN PGP SIGNATURE----- > > iD8DBQFFnlrqtZHp/AYZiNkRAsISAJwNZn6KHQA8Cz64R1xieZjL+unUaQCgsTRI > o1u0l0bFW2stZOZaEFlAfdU> =Vkpv > -----END PGP SIGNATURE----- > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
So Marius debunked my "improvement" to escapeHTML but did prove that other methods can be much faster. However, what are your thoughts on removing the usage of escapeHTML from _attributes altogether? I think Builder.node needs to be optimized for speed as much as possible since it is something that could be called thousands of times easily. I will be looking into the usage of cloneNode to help alleviate this, but the code probably won''t be as neat and I won''t always be able to use cloneNode. Thanks, Colin Thomas Fuchs wrote:> > > Am 04.01.2007 um 13:19 schrieb Colin Mollenhour: > >> On 2), why can''t the escapeHTML function create a div node and a >> text node once one the first call and reuse it on subsequent calls? >> Also, is this not a leak? >> ------------For reference--------- >> escapeHTML: function() { >> var div = document.createElement(''div''); >> var text = document.createTextNode(this); >> div.appendChild(text); >> return div.innerHTML; >> }, >> ---------------------------------- > > That''s something we''d need to measure. The text node creation > wouldn''t go away, and reusing the div node would mean to empty it out > before adding the text node. I don''t really think that it would make > a real difference. > > Best, > Thomas > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Hi, If not removing it completely, I would go for a way (options, second version etc) to turn it off. Sometimes I even think of a global flag for that. Have been playing around with symfony now for a while. I guess Ruby includes it same way. Shouldn''t in the framework case the framework escape everything while generating the Javscript code? So I would go further and say that scriptaculous can even expect getting escaped text. But since there are manual users who might need it I would like to have a switch for it, as it is, like Colin mentioned, a big hit there. .: Fabian -----Original Message----- From: Colin Mollenhour Sent: Samstag, 6. Januar 2007 03:36 To: rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org Subject: [Rails-spinoffs] Re: SAU/Prototype performance So Marius debunked my "improvement" to escapeHTML but did prove that other methods can be much faster. However, what are your thoughts on removing the usage of escapeHTML from _attributes altogether? I think Builder.node needs to be optimized for speed as much as possible since it is something that could be called thousands of times easily. I will be looking into the usage of cloneNode to help alleviate this, but the code probably won''t be as neat and I won''t always be able to use cloneNode. Thanks, Colin --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Christophe Porteneuve wrote:> Great page, Marius, but I find oddly faster results in my Firefox 2 > (Iceweasel branded, I run Debian): > > Browser: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/20061024 > Iceweasel/2.0 (Debian-2.0+dfsg-1) > Timing 1000 iterations of Prototype, Prototype-oneDiv, String.replace, > String.split...^ 1000 iterations. I used 10000 (ten thousands) iterations. - -- Marius Feraru -----BEGIN PGP SIGNATURE----- iD8DBQFFn1cOtZHp/AYZiNkRAuWMAJ9GH49EazRLg+KP3EcEXs/824aUMQCfaubg ZWJbemGuNwGGH+7HmO7Mb4Y=+e4V -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
I have tried on Safari and Firefox MAC, safari rocks with prototype :) Browser: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv: 1.8.1.1) Gecko/20061204 Firefox/2.0.0.1 Timing 10000 iterations of Prototype, Prototype-oneDiv, String.replace, String.split... Prototype: 1.027s @ 9737/s (n=10000) Prototype-oneDiv: 1.407s @ 7107/s (n=10000) String.replace: 0.350s @ 28571/s (n=10000) String.split: 0.648s @ 15432/s (n=10000) Rate Prototype-oneDiv Prototype String.split String.replace Prototype-oneDiv 7107/s -- -27% -54% -75% Prototype 9737/s 37% -- -37% -66% String.split 15432/s 117% 58% -- -46% String.replace 28571/s 302% 193% 85% -- Tests duration: 3.432 seconds. Total duration: 6.867 seconds. Browser: Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/ 418.9.1 (KHTML, like Gecko) Safari/419.3 Timing 10000 iterations of Prototype-oneDiv, Prototype, String.replace, String.split... Prototype-oneDiv: .385s @ 25974/s (n=10000) Prototype: .365s @ 27397/s (n=10000) String.replace: .591s @ 16920/s (n=10000) String.split: .421s @ 23753/s (n=10000) Rate String.replace String.split Prototype- oneDiv Prototype String.replace 16920/s -- -29% -35% -38% String.split 23753/s 40% -- -9% -13% Prototype-oneDiv 25974/s 54% 9% -- -5% Prototype 27397/s 62% 15% 5% -- Tests duration: 1.762 seconds. Total duration: 5.619 seconds. On Jan 6, 2007, at 9:00 AM, Marius Feraru wrote:> > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Christophe Porteneuve wrote: >> Great page, Marius, but I find oddly faster results in my Firefox 2 >> (Iceweasel branded, I run Debian): >> Browser: Mozilla/5.0 (X11; U; Linux i686; fr; rv:1.8.1) Gecko/ >> 20061024 >> Iceweasel/2.0 (Debian-2.0+dfsg-1) >> Timing 1000 iterations of Prototype, Prototype-oneDiv, >> String.replace, >> String.split... > > ^ 1000 iterations. I used 10000 (ten thousands) iterations. > > - -- > Marius Feraru > -----BEGIN PGP SIGNATURE----- > > iD8DBQFFn1cOtZHp/AYZiNkRAuWMAJ9GH49EazRLg+KP3EcEXs/824aUMQCfaubg > ZWJbemGuNwGGH+7HmO7Mb4Y> =+e4V > -----END PGP SIGNATURE----- > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Colin Mollenhour wrote:> (I was able to reproduce your results, only mine were a lot faster > across the board, what CPU are you using?)As already mentioned, I run all the tests with ten thousands iterations (vs the default "one thousand" value which I suppose you used too). My tests were done on a very "experimentalish" Linux system, host processors are "Intel(R) Pentium(R) 4 CPU 3.00GHz", each guest host having 512MB RAM allocated (no swapping occured during tests). Sorry about this misleading "trick", 1K is a safe default for people who want to get a quick glance, but I used a larger samples number to get more trustworthy results. OFC, I could have used even more iterations, but 10K was enough to get a smooth variation between different executions (at least for those "Prototypish" methods). For instance, a 100K run on Firefox will show similar results (comparing to previous rating): Browser: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20061222 Firefox/2.0.0.1 Timing 100000 iterations of Prototype, Prototype-oneDiv, String.replace, String.split... Prototype: 27.664s @ 3615/s (n=100000) Prototype-oneDiv: 39.626s @ 2524/s (n=100000) String.replace: 8.138s @ 12288/s (n=100000) String.split: 12.519s @ 7988/s (n=100000) Rate Prototype-oneDiv Prototype String.split String.replace Prototype-oneDiv 2524/s -- -30% -68% -79% Prototype 3615/s 43% -- -55% -71% String.split 7988/s 217% 121% -- -35% String.replace 12288/s 387% 240% 54% -- Tests duration: 87.947 seconds. Total duration: 103.594 seconds.> Even though String.replace is slower in Opera I''d be in favor of it > since Opera clearly has some room for improvement with that function > so I''m guessing this may be improved in the future.Hm, as previously stated, browsers behave very different, and Sbastien''s tests just completed the picture. Thanks. I wonder, even after running all these tests, which would be the really best overall choice? I for one cannot clearly see a winner. OFC, YMMV. I remember I worked long time ago on a tool that consolidates different runs of the same benchmark, I guess it could help us getting a better overview... but I''m a mess, have no idea about the when, where or for. Anyway, should be simple enough to write from scratch (maybe even in JavaScript)... we''ll see. ;-) Browser dependent implementations could be a choice, but really!?! Is this the way to go? I really doubt it, and I''m sure many will second me on this one, based on previous conversation, both on this list and on our bug tracker. Sure, we should work on optimizing things, but I''m not too sure about this particular case ("escapeHTML"). In this case, maybe settling to your previous solution (avoiding escapeHTML for Builder.node attributes) would be a safer resolution for now, even if it''s plain wrong (purist talk here: if one test fails, everything should get back to the drawing board). I know, web developers are not generally like that, as they''re getting disappointed every day by existent "platforms". cheers. - -- Marius Feraru -----BEGIN PGP SIGNATURE----- iD8DBQFFn2P3tZHp/AYZiNkRAqKPAKCI3V2dyByhVHgfcs67TUPTZLlRAACgtE+t HHrFr6kNgBzUmoYQ7wlAG8Q=Xz9L -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Marius Feraru wrote:> I remember I worked long time ago on a tool that consolidates different > runs of the same benchmark, I guess it could help us getting a better > overview... but I''m a mess, have no idea about the when, where or for. > Anyway, should be simple enough to write from scratch (maybe even in > JavaScript)... we''ll see. ;-)Hm, reply to myself, not good. But anyway, curiosity killed the cat. So I baked a quick hack to see what are we talking about. Collin, prepare to laugh :) A. Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20061222 Firefox/2.0.0.1 B. Opera/9.10 (X11; Linux i686; U; en) C. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; FDM) D. Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) E. Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) F. Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv: 1.8.1.1) Gecko/20061204 Firefox/2.0.0.1 G. Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/ 418.9.1 (KHTML, like Gecko) Safari/419.3 Method execution rate (per second) per browser: Method A B C D E F G Prototype 3535 18051 4355 4303 3929 9737 27397 Prototype-oneDiv 2635 17575 5294 5679 4070 7107 25974 String.replace 15625 9242 15974 20325 3660 28571 16920 String.split 7675 28169 9009 7407 3911 15432 23753 Top method per browser: Method A B C D E F G AVG Prototype 3 2 4 4 2 3 1 2.71 Prototype-oneDiv 4 3 3 3 1 4 2 2.86 String.replace 1 4 1 1 4 1 4 2.29 String.split 2 1 2 2 3 2 3 2.14 Collin, checkout the average column (AVG)? :) So, String.replace gets most tops, but also gets most bottoms. :) The funniest thing is that String.split looks like being the best choice. UGLY! I always hated that solution (for its ugliness if nothing else) ;-) ... please prove me I''m wrong :) - -- Marius Feraru -----BEGIN PGP SIGNATURE----- iD8DBQFFn4OvtZHp/AYZiNkRAtWjAJ49RF5MXAFcccHbXNnjciurcRybtQCgjAqO 6//6zcb7E/ncp1oXGR7cXbs=l9DZ -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Colin, I have great news :) After more brainstorming, we (mishoo and I) came up with some updates to my previous test, the most important thing being that we have a new winner :) We baked two more methods: String.replaceMap (a sloppy variant of String.replace), and Prototype.oneDiv2 (a variant of Prototype.oneDiv which does caches the textNode too). More updates: - - change text after each test (adding/changing trailing digits - to avoid any hypothetical browsers'' cache tricks); - - dropped escaping """ (to play similar to "oneDiv" methods); - - changed default iterations number to "10000" (to avoid future confusion). OK, without further ado, here are the consolidated results: Benchmarks run using 10000 iterations on these browsers: A. Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20061222 Firefox/2.0.0.1 B. Opera/9.10 (X11; Linux i686; U; en) C. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; FDM) D. Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) E. Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) F. Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.8.1 (KHTML, like Gecko) Safari/312.6 G. Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0 Method execution rate (per second) per browser: Method A B C D E F G Prototype 3197 17094 4182 3959 4704 3598 3162 Prototype.oneDiv 2548 16529 5005 4006 5283 5851 1826 Prototype.oneDiv2 8170 51020 13405 8258 10953 13477 6588 String.replace 15175 6739 15699 4468 15949 1604 10526 String.replaceMap 8905 9699 12804 4008 16584 1694 6540 String.split 10163 27322 9681 4983 10373 1730 6954 Top method per browser: Method A B C D E F G AVG Prototype 5 3 6 6 6 3 5 4.86 Prototype.oneDiv 6 4 5 5 5 2 6 4.71 Prototype.oneDiv2 4 1 2 1 3 1 3 2.14 String.replace 1 6 1 3 2 6 1 2.86 String.replaceMap 3 5 3 4 1 5 4 3.57 String.split 2 2 4 2 4 4 2 2.86 Sorry, I have no Intel based Mac available at this hour, maybe Sbastien could help us. ;-) cheers - -- Marius Feraru -----BEGIN PGP SIGNATURE----- iD8DBQFFn6i1tZHp/AYZiNkRAgcuAKDvaLyJrfZ4BvCh/Q5eIaZvSuy1vQCgxfCu 6o4cDXbL6QMgO0GVPJt0vJY=abUL -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Marius Feraru wrote:> Sorry, I have no Intel based Mac available at this hour, maybe Sbastien > could help us. ;-)Talked too soon, my folks are still alive ;-) Benchmarks run using 10000 iterations on these browsers: A. Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20061222 Firefox/2.0.0.1 B. Opera/9.10 (X11; Linux i686; U; en) C. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; FDM) D. Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) E. Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) F. Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.8.1 (KHTML, like Gecko) Safari/312.6 G. Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0 H. Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1 I. Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418 (KHTML, like Gecko) Safari/417.9.2 Method execution rate (per second) per browser: Method A B C D E F G H I Prototype 3197 17094 4182 3959 4704 3598 3162 8803 24096 Prototype.oneDiv 2548 16529 5005 4006 5283 5851 1826 6017 20833 Prototype.oneDiv2 8170 51020 13405 8258 10953 13477 6588 16667 39841 String.replace 15175 6739 15699 4468 15949 1604 10526 32051 20619 String.replaceMap 8905 9699 12804 4008 16584 1694 6540 15221 24213 String.split 10163 27322 9681 4983 10373 1730 6954 17241 27548 Top method per browser: Method A B C D E F G H I AVG Prototype 5 3 6 6 6 3 5 5 4 4.78 Prototype.oneDiv 6 4 5 5 5 2 6 6 5 4.89 Prototype.oneDiv2 4 1 2 1 3 1 3 3 1 2.11 String.replace 1 6 1 3 2 6 1 1 6 3.00 String.replaceMap 3 5 3 4 1 5 4 4 3 3.56 String.split 2 2 4 2 4 4 2 2 2 2.67 So this new method really looks like being our winner ;-) - -- Marius Feraru -----BEGIN PGP SIGNATURE----- iD8DBQFFn60gtZHp/AYZiNkRAm7PAJ9lOvg+9xB95P0UrgB+c3QlqK94ZgCfWslH n3KwHx5c+goOZeVUY26dJfU=8PFS -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Excellent work! The oneDiv2 function really does shine but considering the prevalence of FF and IE6/7, I would still be hard pressed to choose it over String.replace. Either way, they are both a big improvement over the original Prototype method (with the exception of String.replace for Opera and Intel Safari). Take the last step and submit a patch with your results to back it up :) Thanks, Colin Marius Feraru wrote:> > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Marius Feraru wrote: >> Sorry, I have no Intel based Mac available at this hour, maybe S bastien >> could help us. ;-) > Talked too soon, my folks are still alive ;-) > > Benchmarks run using 10000 iterations on these browsers: > A. Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20061222 > Firefox/2.0.0.1 > B. Opera/9.10 (X11; Linux i686; U; en) > C. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR > 2.0.50727; FDM) > D. Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like > Gecko) > E. Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) > F. Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.8.1 > (KHTML, like Gecko) Safari/312.6 > G. Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1) > Gecko/20061010 Firefox/2.0 > H. Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.1) > Gecko/20061204 Firefox/2.0.0.1 > I. Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418 > (KHTML, like Gecko) Safari/417.9.2 > > Method execution rate (per second) per browser: > Method A B C D E F G > H I > Prototype 3197 17094 4182 3959 4704 3598 3162 > 8803 24096 > Prototype.oneDiv 2548 16529 5005 4006 5283 5851 1826 > 6017 20833 > Prototype.oneDiv2 8170 51020 13405 8258 10953 13477 6588 > 16667 39841 > String.replace 15175 6739 15699 4468 15949 1604 10526 > 32051 20619 > String.replaceMap 8905 9699 12804 4008 16584 1694 6540 > 15221 24213 > String.split 10163 27322 9681 4983 10373 1730 6954 > 17241 27548 > > Top method per browser: > Method A B C D E F G > H I AVG > Prototype 5 3 6 6 6 3 5 > 5 4 4.78 > Prototype.oneDiv 6 4 5 5 5 2 6 > 6 5 4.89 > Prototype.oneDiv2 4 1 2 1 3 1 > 3 3 1 2.11 > String.replace 1 6 1 3 2 6 1 > 1 6 3.00 > String.replaceMap 3 5 3 4 1 5 > 4 4 3 3.56 > String.split 2 2 4 2 4 4 2 > 2 2 2.67 > > > So this new method really looks like being our winner ;-) > > - -- > Marius Feraru > -----BEGIN PGP SIGNATURE----- > > iD8DBQFFn60gtZHp/AYZiNkRAm7PAJ9lOvg+9xB95P0UrgB+c3QlqK94ZgCfWslH > n3KwHx5c+goOZeVUY26dJfU> =8PFS > -----END PGP SIGNATURE----- > > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Colin Mollenhour wrote:> The oneDiv2 function really does shine but considering the prevalence of > FF and IE6/7, I would still be hard pressed to choose it over > String.replace.And if we notice how different FF behaves on each platform (comparing to Opera for instance), the choice becomes even more difficult, at least if we would have chosen to implement different solutions for each browser/platform.> Take the last step and submit a patch with your results to back it up :)OK. Submitted as ticket #6937: http://dev.rubyonrails.org/ticket/6937 - -- Marius Feraru -----BEGIN PGP SIGNATURE----- iD8DBQFFoMjOtZHp/AYZiNkRAiUeAKCvKWIGvoYRu6FrEvWWrCCuHaoJzACgr6ZB ZiiB2wHFNHiXmYilnNig5aw=98h3 -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Colin Mollenhour wrote:> Excellent work! The oneDiv2 function really does shine but considering > the prevalence of FF and IE6/7, I would still be hard pressed to choose > it over String.replace.Also consider that while innerHTML has been widely copied, it has no public standard whereas String.replace does. It is known that different browsers will return different innerHTML given identical HTML source or piece of DOM tree. Having it as the basis for a kind of ''normalise'' function doesn''t make sense - speed should not be the sole criterion. -- Fred --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Here are the results from my Quad G5: Safari: --------- Browser: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/ 418.9.1 (KHTML, like Gecko) Safari/419.3 Timing 10000 iterations of Prototype, Prototype.oneDiv, Prototype.oneDiv2, String.replace, String.replaceMap, String.split... Prototype: .610s @ 16393/s (n=10000) Prototype.oneDiv: .594s @ 16835/s (n=10000) Prototype.oneDiv2: .331s @ 30211/s (n=10000) String.replace: .871s @ 11481/s (n=10000) String.replaceMap: .789s @ 12674/s (n=10000) String.split: .975s @ 10256/s (n=10000) Webkit r18654: --------------------- rowser: Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/ 420+ (KHTML, like Gecko) Safari/419.3 Timing 10000 iterations of Prototype, Prototype.oneDiv, Prototype.oneDiv2, String.replace, String.replaceMap, String.split... Prototype: 0.376s @ 26596/s (n=10000) Prototype.oneDiv: 0.277s @ 36101/s (n=10000) Prototype.oneDiv2: 0.153s @ 65359/s (n=10000) String.replace: 0.738s @ 13550/s (n=10000) String.replaceMap: 2.062s @ 4850/s (n=10000) String.split: 0.228s @ 43860/s (n=10000) Firefox: ---------- Browser: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; de; rv: 1.8.1.1) Gecko/20061204 Firefox/2.0.0.1 Timing 10000 iterations of Prototype, Prototype.oneDiv, Prototype.oneDiv2, String.replace, String.replaceMap, String.split... Prototype: 1.543s @ 6481/s (n=10000) Prototype.oneDiv: 2.365s @ 4228/s (n=10000) Prototype.oneDiv2: 0.790s @ 12658/s (n=10000) String.replace: 0.606s @ 16502/s (n=10000) String.replaceMap: 1.027s @ 9737/s (n=10000) String.split: 0.953s @ 10493/s (n=10000) Note how the latest Safari Webkit Nightly runs circles around Firefox with 65359/s, wow... 8O Best, Thomas Am 06.01.2007 um 15:07 schrieb Marius Feraru:> > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Marius Feraru wrote: >> Sorry, I have no Intel based Mac available at this hour, maybe >> Sébastien >> could help us. ;-) > Talked too soon, my folks are still alive ;-) > > Benchmarks run using 10000 iterations on these browsers: > A. Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/ > 20061222 Firefox/2.0.0.1 > B. Opera/9.10 (X11; Linux i686; U; en) > C. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR > 2.0.50727; FDM) > D. Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like > Gecko) > E. Mozilla/4.0 (compatible; MSIE 6.0; Windows 98) > F. Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/312.8.1 > (KHTML, like Gecko) Safari/312.6 > G. Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1) > Gecko/20061010 Firefox/2.0 > H. Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US; rv:1.8.1.1) > Gecko/20061204 Firefox/2.0.0.1 > I. Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/418 > (KHTML, like Gecko) Safari/417.9.2 > > Method execution rate (per second) per browser: > Method A B C D E F > G H I > Prototype 3197 17094 4182 3959 4704 3598 3162 > 8803 24096 > Prototype.oneDiv 2548 16529 5005 4006 5283 5851 1826 > 6017 20833 > Prototype.oneDiv2 8170 51020 13405 8258 10953 13477 6588 > 16667 39841 > String.replace 15175 6739 15699 4468 15949 1604 10526 > 32051 20619 > String.replaceMap 8905 9699 12804 4008 16584 1694 6540 > 15221 24213 > String.split 10163 27322 9681 4983 10373 1730 6954 > 17241 27548 > > Top method per browser: > Method A B C D E F > G H I AVG > Prototype 5 3 6 6 6 3 > 5 5 4 4.78 > Prototype.oneDiv 6 4 5 5 5 2 > 6 6 5 4.89 > Prototype.oneDiv2 4 1 2 1 3 1 > 3 3 1 2.11 > String.replace 1 6 1 3 2 6 > 1 1 6 3.00 > String.replaceMap 3 5 3 4 1 5 > 4 4 3 3.56 > String.split 2 2 4 2 4 4 > 2 2 2 2.67 > > > So this new method really looks like being our winner ;-) > > - -- > Marius Feraru > -----BEGIN PGP SIGNATURE----- > > iD8DBQFFn60gtZHp/AYZiNkRAm7PAJ9lOvg+9xB95P0UrgB+c3QlqK94ZgCfWslH > n3KwHx5c+goOZeVUY26dJfU> =8PFS > -----END PGP SIGNATURE----- > > >-- Thomas Fuchs wollzelle http://www.wollzelle.com questentier on AIM madrobby on irc.freenode.net http://www.fluxiom.com :: online digital asset management http://script.aculo.us :: Web 2.0 JavaScript http://mir.aculo.us :: Where no web developer has gone before --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---