Which is faster, calling helpers or rendering a partial?

Using partials is a nice way to separate chunks of content into
separate pages as opposed to building strings in helpers, but I’m
wondering which is faster. It scares me when I see stuff like:

Rendered users/_public (0.00051)
Rendered users/_public (0.00009)
Rendered users/_public (0.00008)
Rendered users/_public (0.00008)
Rendered users/_public (0.00008)
…50 more times

Has anyone done some benchmarking? I’d like to use partials if I
could, but not if they’re slower.

Thanks,
PJ

On Apr 27, 2006, at 02:12 PM, PJ Hyett wrote:

Has anyone done some benchmarking? I’d like to use partials if I
could, but not if they’re slower.

I’ve been seeing questions similar to this over the past couple of
weeks and I have to say that I’m a bit confused by them. At what
point did people start thinking partial page templates were somehow
in competition with view helper methods?

Partials are how you handle chunks of repetitive HTML in your views.
They are rendered through eRb and designed to fit seamlessly in your
page templates. I won’t go into the benefits of
“render :partial… :collection” here. Suffice it to say, if you are
putting looping code into your page templates, just stop it, now.
You’ll thank me later. :slight_smile:

View helper methods are a way to take a particular bit of complex,
usually conditional, view logic and move it out of your eRb code,
replacing it with a single method call. While you can use it to
construct several lines of eRb code, doing so simply makes no sense
to me. Where I tend to use helpers is when I’ve got a form control,
usually a button, that only needs to display (or display in a certain
way) based on the logged in user, or some other programmatic setting.
I almost never use a helper to return more than a single page
element, mostly because that’s what seems to make the most sense to me.

Helper methods are designed to work, in cooperation, with your view
templates. All your view templates. Including your partials. There’s
no competition here and, I would argue, no overlap in functionality…

-Brian

Thanks for the response Brian. I understand the intended purpose for
helpers and partials, but I need to make the pages load quickly
regardless if it’s not the “right” thing to do.

-PJ

On Apr 27, 2006, at 02:36 PM, PJ Hyett wrote:

Thanks for the response Brian. I understand the intended purpose for
helpers and partials, but I need to make the pages load quickly
regardless if it’s not the “right” thing to do.

Well, I’ve never run any benchmarks, but based on what you’re seeing
in your log files, I’d say that you using
render :partial… :collection to loop over an array of objects.
That’s exactly what you should be doing. And the :collection feature
is the “right”, and I would think, the best way to handle this.

Also, if you were to replicate this in a helper, you are basically
duplicating code that’s already built into Rails, for you to use.
That seems odd to me. Finally, you would have build up large string
object, in the helper, that you then have to pass back to your view.
All of these things, taken together, I think clearly demonstrate why
you should stick with render :partial… :collection.

-Brian

If you through in a little caching, your tests will equal out. You
should then choose the action that is the most appropriate for what
you’re doing.

I just threw together a dead simple test putting partials and helpers
up head-to-head. I’m not sure this is all that effective of a test,
but I thought it was worth trying.

Short version (load times):
Partial (0.01553)
Helper (0.00030)

Here’s the code I’m using:
—test_controller.rb—
def index
@data = []
1.upto(50){|n| @data << n}
end

—test/_info.rhtml—

—test_helper.rb—
def info(size)
ret = ‘’
1.upto(size) do |n|
ret += %{}
end
ret
end

—test/index.rhtml—
<% benchmark “Partial” do %>
<%= render :partial => ‘info’, :collection => @data %>
<% end %>


<% benchmark "Helper" do %> <%= info %> <% end %>

Again, the results are fairly compelling when you think of it in terms
on a larger scale:
Partial (0.01553)
Helper (0.00030)

-PJ

The reason why I’m trying to optimize these calls is due to the page
having
too many dynamic elements to take advantage of caching in any sort of
broad
way.

-PJ

what about fragment caching?

Two things… unless you are testing this within the production
environment, anything that involves rendering a template file will be
slower than not rendering a template. That’s because Rails makes a
completely new call to render, each time through the :collection loop.

Second, if you honestly feel that hand-stitching HMTL lines together
in a helper is the better way to go, no one on this list will try to
stop you. I expect we’ll all do our best to explain why that’s the
“wrong” way to accomplish what you’re trying to do, but you’ve
already proven that it works, and if you want to simply go by your
numbers, it certainly looks to be quicker.

Speaking for myself, you’d have to pay me some serious cash to go
back to hand-stitching. I gave that up over 6 years ago, when I first
starting using templates to handle my HTML…

-Brian

I am being paid well to make sure the site I’m building isn’t slow.
I’m not trying to be argumentative because I need my blog to load
faster :slight_smile:

Running in production mode, the difference is still fairly large:
Helper (0.00032)
Partial (0.00451)

-PJ

In almost every case a helper is going to outdo a partial. The partial
stuff has been enhanced nicely in 1.1, but it isn’t going to compete
with helpers.

You can avoid a lot (not all) of the HTML stitching by using ERB in-line
in your helpers. It is probably slower than ‘pure’ helpers still, but
probably faster than partials.

In the end you have decide where your time is better spent:
hand-optimizing code for performance or spending more time on features.
In the end we all wind up doing some ugliness for the sake of
performance, but I wouldn’t advise one to start out that way.

Jim P.

PJ Hyett <pjhyett@…> writes:

I just threw together a dead simple test putting partials and helpers
up head-to-head. I’m not sure this is all that effective of a test,
but I thought it was worth trying.

Short version (load times):
Partial (0.01553)
Helper (0.00030)

Hint: page rendering time should be nothing next to the time taken in
business
and database code. Even if helper is ten times faster, it probably won’t
make
any real difference.

– Pazu

PJ,

Every peice of documentation that talks about optimizing code always
says, “optimize last”. The primary reason is there isn’t a good way to
tell upfront where you are going to have the majority of the problems.
Someone has already mentioned that your biggest worry will be database
access. The database is almost always your biggest bottle neck.

We have no idea what type of system you are building or the number of
users you expect to have. Given that, here is some interesting reading
on scaling an application:

http://poocs.net/articles/2006/03/13/the-adventures-of-scaling-stage-1
http://poocs.net/articles/2006/03/20/the-adventures-of-scaling-stage-2
http://poocs.net/articles/2006/03/27/the-adventures-of-scaling-stage-3
http://poocs.net/articles/2006/04/03/the-adventures-of-scaling-stage-4

You will notice that they didn’t spend much time tweaking code. The
savings that you make by tweaking your code will be lost when you add
a new developer who doesn’t understand why you are not following Rails
convention.

Just my 2 cents.

Carl

Just be sure to document in the code why you are making that choice so
when you or anyone else looks at that code in the future it will be
understood that the code was written that way purposefully.

The savings that you make by tweaking your code will be lost when you add
a new developer who doesn’t understand why you are not following Rails
convention.

Agreed, I’ve settled on using partials everywhere except for one spot
where I feel that the helper speedup is worth a slight loss in
readability. Thanks everyone.

-PJ

PJ Hyett wrote:

Thanks for the response Brian. I understand the intended purpose for
helpers and partials, but I need to make the pages load quickly
regardless if it’s not the “right” thing to do.

Maybe you ought to code it in assembly. After the intended purpose of
the framework has been violated, it’ll be just as complex to understand
what you did.