Is calling a partial an expensive operation? - ruby-on-rails

Can I use partials as much as I want or do I have to restrain myself to avoid bringing my views to a crawl under much traffic?

There's an obvious overhead using partial but this isn't something you should probably worry about.
Partials are files. When you render an action without partials, your action "costs" 1 file (that's not totally true, but this is to simplify the explanation).
If your action renders 4 partials, you end up with a cost of 5. This means, you have 4 additional IO calls and the real cost for each call depends on your server load, server performances and so on.
But does this cost matter? In my experience, for the 99% of times no. Also noteworthy, the benefits of using partials in terms of code readability and maintainability usually are worth the choice.
If performances must be a key feature, you should probably look for speed and improvements elsewhere.
Remember: Ruby is not a super-fast programming language and code expressiveness always took the first place in favor of performances. Rails implicitly agree to this convention, albeit the Rails team has always focused on performances (and Rails 3 it's the practical demonstration there's always place for improvements)
That said, you can safely use partials and reduce the application overhead with some clever caching mechanism. For example, you can place collection rendering within a cache block so that a render collection statement will be executed only once then your app will simply load 1 cache file instead of 10 un-cached partials.
One of the most sneak errors I made many times at the beginning was to worry about performances in the wrong way, that said, without actually running benchmarks. I remember once when I was trying to drop one single database query in favor of an hard coded hash because "the query costs", without realizing there was an other stupid query that was loading an entire table collection without the include statement, that resulted in running the second query 3 times slower.
So, if you really care about performance, you probably shouldn't avoid using partials but instead make sure you are taking advantage of all the other features Rails provides you to scale your application.

Related

Could I not use instance variables?

I'm new to Rails and I have a question. Everyone says the preferred way of iterating through a table is to capture the data in an instance variable via a Controller, then iterate in the corresponding View.
What if I just did
<% Course.all.each do |course| %>
<!-- displays list of courses -->
<% end %>
I know using instance variables is the preferred way, but is there any reason?
Could I not use instance variables?
Yes. The code, as you've written it, works.
Using instance variables is the preferred way, but is there any reason?
It's really just an agreed design pattern to do avoid making database queries directly in the view.
A principle of MVC frameworks is to have the controller prepare all data for the view, rather than the view directly fetching data at arbitrary points. In the long term, you'll find the latter approach can become messy, un-performant and difficult to maintain.
For example, you might start making the same query multiple times, or run into N+1 problems, or struggle to test the implementation at all (because if logic is all inside the view, the only way to test might be via very complex+expensive feature tests, instead of quick and easy unit tests!) - which can make the implementation fragile and error prone.
But rules are made to be broken, and you can write code like this in rails; just take a word of warning from the past experience of developers who invented MVC frameworks in the first place: This is generally a design pattern to be avoided.
You certainly CAN do this, but it does not mean it is a good idea.
Rails operates as an MVC framework which separates models, views & controllers, which in turn is really an application of the "Separation of Concerns" design principle.
By adding controller responsibilities (fetching data) into view responsibilities (displaying data & interacting with the users), you're making it more difficult for the view code to be reused.
What if you only want to display a subset of courses but not all of them, but using the same format?
What if you want to display a different set of courses depending on who the user is at the moment?
What if you want to paginate the course list because you've got 1,000 courses already?
And so on.
This is really hard to appreciate when you are just starting out but getting into the habit as early as possible will save yourself from unlearning it later down the line.
At the end of the day, these are just conventions, and there is a time and place wherein you can break conventions but just be aware that all these "rule-breaking" might eventually come back and haunt you. That's what we call "technical debt" and as with any kind of debt, the longer you keep it, the harder it is to pay it off.

Which is better - Output Caching 6 Child Actions or 6 DB queries using RenderPartial?

I am attempting to develop a cms system that will use tags to display similar content. For example, underneath the news section there will be articles, blogs, news and forum questions that share the same tags. There will be no more than 5 items in each list.
I am considering 2 options for displaying this related content and am wondering if developers with more experience than myself would recommend one over the other?
Speed is the primary goal, because we have equally maintainable ways of executing both options.
Option 1 - Output Caching RenderAction Results
For each 'similar content' section, render a child action on the corresponding controller and cache the output. This feels more in the spirit of MVC, and would be light on DB calls. But with 5 'similar content' lists, that would equal 6 full MVC cycles for each page request.
I've read that RenderAction can still be expensive, even though it has improved in the last couple of years.
Option 2 - RenderPartials with DB Queries for Each
Alternatively, for each 'similar content' section, we could query the db and use RenderPartial to display the output. Although this would require a small DB query for each section (5 items or less), I'm wondering how that would compare with the performance saved by NOT calling RenderAction.
I've frequently read how much faster RenderPartial is compared to RenderAction.
Essentially your choice boils down to which is faster: RenderAction with an already cached result or 5 DB queries?
When you look at it that way, you really are talking about one solution with no network latency and one solution with network latency (sending the query to the database and receiving a response). Any solution that removes network latency is de facto faster than an alternative with network latency.
Also, bear in mind that purists like to talk about how one thing or another is "slow" compared to some other way. Yes, child actions will always be slower than partials because child actions go through the whole routing infrastructure and then finally to the Razor template engine whereas partials just go directly to the Razor template engine. But, we're talking about highly optimized, compiled code running in memory. "Slower" is measured in milliseconds or even nanoseconds. Sure, those can add up over time, and if you did something crazy like render 50 child actions in a single view, you might see some noticeable performance loss, but this will typically not be an issue worth worrying about in 99.9999% of cases.
Just design your application in the way that makes the most sense for your application and stop worrying about a millisecond here or there.

RenderAction vs RenderPartial performance

According to Brad Wilson, RenderAction is slower than RenderPartial.
However, has anyone got any statistics that show the difference in performance?
I'm in the process of developing an application where pages are composed of "Widgets".
I have two choices:
Composition at the View Level
Call RenderAction for each widget. This is by far the easiest approach but does mean that we're performing a full MVC cycle for each widget.
Composition at the Controller Level
Compose one ViewModel for the page that contains the data we need for each widget. Call RenderPartial for each widget. This is much more complicated to implement but does mean we'll make only one MVC cycle.
I tested the above approaches with 3 different widgets on a page and the difference in render time was 10ths of a second (hardly worth worrying about).
However, has anyone got any test results more concrete than this, or perhaps experience trying both approaches?
I've recently worked on an application that was experiencing performance issues, and found a view that was making four calls to RenderAction, plus another one in the layout. I found that each call to RenderAction--even when I added in a dummy action that returned an empty view--took around 200-300ms (on my local machine). Multiply by the number of calls and you have a huge performance hit on the page. In my case there were four calls causing about a second of unecessary server-side overhead. By comparison, calls to RenderPartial were around the area of 0-10ms.
I would avoid using RenderAction wherever possible in favor of RenderPartial. The controller should be responsible for returning all necessary information. In the case of widgets, if you need multiple actions for several widgets, I would try composing them into one action so the RenderAction overhead only occurs once, though if your site performs adequately I'd keep them separate for a cleaner design.
Edit: I gathered this information using MiniProfiler and hitting the site. It isn't super accurate but it does clearly show the differences.
Edit: As Oskar pointed out below, the application in question likely had some intensive code that runs for each request in global.asax. The magnitude of this hit will depend on the application code, but RenderPartial will avoid executing another MVC cycle altogether.
I'd suggest 2 more options, both require to compose the view model at Controller level and both can work together (depending on the data)
Html.DisplayFor() - display templates
Helpers via extension methods
Option 2 works very well if you want to keep those widgets in different assemblies, after all they're just functions returning a string. I think it has also the best performance, but of course you lose the 'designer friendly' templates. I think it's important to consider the maintainability aspect, not only raw performance (until you really need it, and even then, caching is more helpful).
For small stuff (date or name formatting etc) i'd use helpers, since the html is usually a span with a class, for more complex stuff I'd use the display templates.

What's the overhead of including RenderPartial in an MVC3 page

I am trying to optimize my code as much as possible. I use a lot of partial files like this:
#if (Model.PageMeta.Sidebar == PageMetaSidebar.Small) { Html.RenderPartial("_SmallSidebar"); }
..
..
..
Can someone tell me if there is a performance overhead with this. I understand that Razor views are compiled. Is it the case that when the page is displays there is another disk read to get the data for each of the partial files that I use. If that's the case then how much additional overhead could I expect with for example 5 RenderPartials on my layout page.
There will be no noticable performance hit at all here as the partials are just pulled in on the asp.net web server before streaming the resultant HTML back to the browser. This is not an expensive disk read to do and won't appear any slower than if it was a single cshtml. Obviously partials should be used if the same partial view is reused in many views. If only used in a single view then it's just a matter of clarity splitting it into a separate partials to separate parts of your model into different views.
Note you can also just use:
#Html.Partial("YourPartial")
rather than using RenderPartial. This will look in the local view folder then in shared if not found.
I don't think using RenderPartial ~5 times is going to have a significant enough impact to design your pages poorly. If it makes sense to pull the logic out (makes the page cleaner, used by multiple views, etc.) then do it. If you notice significant performance issues then you should look at them at that time, but don't prematurely optimize and create a poor design because you THINK it might slow something down.
If you like to get a better understanding of potential performance hits you might want to play around with the mvc-mini-profiler.
Please note though that I'm not advocating pre-mature optimization. However, using profiling tools might give you a better understanding of potential bottlenecks, thus helping you avoid them in the future.

Best Practices for using partials in Rails

In keeping with the DRY-principle I try to use partials as soon as I am repeating a particular pattern more than once or twice. As a result, some of my views consist of ten or more different partials. I am worried that this might have a negative effect on the overall performance. Some programming books compare the use of partials with the use of methods. So should I use the same rationale to determine when to use them?
What is the best practice regarding size and quantity of partials in a Rails project?
I like your practice already: Once you've repeated view code twice, refactor it out to a partial. Tim's right that you can speed it up as necessary after it's been profiled and after it's been proven necessary.
Here is my one caveat: If you work with professional designers who handle the views, it may be easier over the long term to have rather repetitive view code. Some people have a hard time searching through partials and "seeing" how they all fit together. I've found it easier with those people to let them manage the whole shebang and update more than one file if they need to. Optimal? Not to us as programmers, but designers are more often used to seeing most of the HTML in one or three files rather than 20. :)
Remember the rules of optimization!
If, once your application is complete, your views are too slow, use something like New Relic to find out where the slowdown is occurring. There are a lot of places that might be, but it's unlikely to be in your partials.

Resources