Horribly Slow RJS/Ajax Rendering Compared to Non?

Hi, I’m seeing some pretty bad numbers when doing Ajax updates in the
Rails logs, compared to rendering the same thing without ajax.

On a complete browser refresh, which is using render_component, I am
seeing the main content of my application render at 42 req/s, 22 req/s
overall when including the layout outside of the rendered component.

When I click a link that renders the same exact content as the
render_component does, I get 5-8 req/s.

This is 5 times slower… just to wrap it up in a Element.update. Is the
Ajax/RJS implementation that bad? Or am I missing something? Is it
javascript escaping in some horribly inefficient way?

Ie. ajax was supposed to make things go faster, lol, not 5 times slower.
The page does load faster overall, but why is the performance sooo bad?

There are cases in which rjs is not optimal.
If your ajax call generates a large amount of rhtml then that rhtml has
to be escaped so that it fits into a javascript string, and then on the
browser side, the client has to parse that large chunk of javascript and
execute it.
So if your rjs is just page.replace_html foo or page.insert_html foo
then you are often better off using the :update option of link_to_remote
and friends.

Fred

That’s a big slowdown for a reasonably small amount of js. I had
nothing like that much of a slow down with a rather big page load.
Have you tried using action_profiler
(http://rails-analyzer.rubyforge.org/action_profiler/) to see exactly
where the time is going?

Fred wrote:

That’s a big slowdown for a reasonably small amount of js. I had
nothing like that much of a slow down with a rather big page load.
Have you tried using action_profiler
(http://rails-analyzer.rubyforge.org/action_profiler/) to see exactly
where the time is going?

I haven’t played around with action_profiler since I made the to_json
patch. The main problem with action_profiler is that it having it tell
me it spend 10% of its time in Kernel#=== isn’t as helpful as it could
be :P. I’ve installed the eval version of Ruby Performance Validator,
which supposedly has call graphs, but I have no idea how to run it on a
Rails app, and there’s no docs that I have been able to find on doing
so, and no response from a support email I sent them.

Performance is much closer to what I would expect, with the to_json
patch, it’s just so hard to tell, cause half the time the a request goes
thru at 32 req/sec the other times at 12…with no real obvious reason
for it, besides some really bad garbage collection.

Fred wrote:

There are cases in which rjs is not optimal.
If your ajax call generates a large amount of rhtml then that rhtml has
to be escaped so that it fits into a javascript string, and then on the
browser side, the client has to parse that large chunk of javascript and
execute it.
So if your rjs is just page.replace_html foo or page.insert_html foo
then you are often better off using the :update option of link_to_remote
and friends.

Fred

Yes it appears escaping is the culprit. Adding the to_json patch from
http://dev.rubyonrails.org/ticket/3473 seems to help considerably,
though escape_javascript in 1.1.6 doesn’t use to_json it, so must be
getting used somewhere else. And performance could be better even
still.

I’m not really concerned with browser side performance. We are talking
5K worth of data, is that ‘large amount’? So, I’m guessing that
link_to_remote :update doesn’t need to have anything escaped would be
the difference… unfortunately, that sort of limits my options. Ie.
If someone tries to adjust a slider when they arent logged in, I want to
update a flash div, as well as redraw the sliders back to their unmoved
state, for example.

Are the internals of gsub able to handle this stuff efficiently? Ie.,
are too many reallocation/copies happening because of the number of
extra chars that are being added to escape the various punctuation and
whitespace? Are there ways to have it preallocate enough space (2x the
string size would be the obvious choice, in the worst case scenario of
all escaped chars.) And this really kind of screws with fragment caching
too, since if 80% of the cost of a method is escaping the javascript
lol…I don’t care how you do it, 500% increase in rendering time due
to escaping is pretty bad.

Thanks.