Is rendering more partials reduce performance in Rails web application? - ruby-on-rails
I have created Rails(version - 5.0.0.1) application. I have used partials for reduce the repeated code. I have completed the feature, after saw the console log for particular request there was at least 100 partials rendered and it may goes upto 200. Is this affect the application performance ?
Following is console log when processing request.
Started GET “/******/98747259/edit" for 127.0.0.1 at 2017-04-19 14:51:50 +0530
Processing by *********Controller#edit as HTML
Parameters: {}
Rendering triggers/edit.html.erb within layouts/application
Rendered layouts/_navigation_menu.html.erb (18.8ms)
Rendered layouts/_flash_errors.html.erb (1.5ms)
Rendered triggers/trigger/_campaign.html.erb (5.2ms)
Rendered triggers/trigger/_campaign.html.erb (2.3ms)
Rendered triggers/trigger/_campaign.html.erb (2.1ms)
Rendered triggers/trigger/_campaign.html.erb (1.7ms)
Rendered triggers/trigger/_campaign.html.erb (2.0ms)
Rendered triggers/trigger/_campaign.html.erb (2.3ms)
Rendered triggers/trigger/_campaign.html.erb (1.8ms)
Rendered triggers/trigger/_campaign.html.erb (94.5ms)
Rendered triggers/trigger/_campaign.html.erb (2.2ms)
Rendered triggers/trigger/_campaign.html.erb (2.5ms)
Rendered triggers/actions/_add_tag_elements.html.erb (1.5ms)
Rendered triggers/actions/_add_tag_elements.html.erb (0.8ms)
Rendered triggers/actions/_add_tag_elements.html.erb (0.8ms)
Rendered triggers/actions/_tag.html.erb (15.9ms)
Rendered triggers/actions/_add_tag_elements.html.erb (0.7ms)
Rendered triggers/actions/_add_tag_elements.html.erb (0.8ms)
Rendered triggers/actions/_add_tag_elements.html.erb (0.8ms)
Rendered triggers/actions/_tag.html.erb (9.2ms)
Rendered triggers/actions/_add_campaign_elements.html.erb (2.4ms)
Rendered triggers/actions/_add_campaign_elements.html.erb (1.8ms)
Rendered triggers/actions/_campaign.html.erb (103.3ms)
Rendered triggers/actions/_add_campaign_elements.html.erb (2.0ms)
Rendered triggers/actions/_add_campaign_elements.html.erb (1.7ms)
Rendered triggers/actions/_campaign.html.erb (7.7ms)
Rendered triggers/actions/_add_multiple_campaigns_elements.html.erb (8.3ms)
Rendered triggers/actions/_add_multiple_campaigns_elements.html.erb (76.3ms)
Rendered triggers/actions/_multiple_campaigns.html.erb (91.8ms)
Rendered triggers/actions/_add_campaign_elements.html.erb (1.7ms)
Rendered triggers/actions/_add_campaign_elements.html.erb (3.0ms)
Rendered triggers/actions/_campaign.html.erb (8.7ms)
Rendered triggers/actions/_add_email_elements.html.erb (6.8ms)
Rendered triggers/actions/_add_email_elements.html.erb (2.1ms)
Rendered triggers/actions/_add_email_elements.html.erb (2.1ms)
Rendered triggers/actions/_email.html.erb (18.4ms)
Rendered triggers/actions/_add_custom_field_elements.html.erb (1.2ms)
Rendered triggers/actions/_custom_field.html.erb (4.3ms)
Rendered triggers/actions/_delete_subscriber.html.erb (1.2ms)
Rendered triggers/actions/_add_unsubscribe_elements.html.erb (1.4ms)
Rendered triggers/actions/_add_unsubscribe_elements.html.erb (0.6ms)
Rendered triggers/actions/_unsubscribe.html.erb (12.4ms)
Rendered triggers/actions/_modal_for_mail.html.erb (1.0ms)
Rendered triggers/_add_new_action.html.erb (1.4ms)
Rendered triggers/actions/_unsubscribe_from_campaign.html.erb (3.2ms)
Rendered triggers/perform_actions/_apply_or_remove_tags.html.erb (1.0ms)
Rendered triggers/perform_actions/_campaign.html.erb (0.9ms)
Rendered triggers/perform_actions/_move_from_one_campaign_to_another.html.erb (1.4ms)
Rendered triggers/perform_actions/_send_manual_mail.html.erb (2.5ms)
Rendered triggers/perform_actions/_set_custom_field.html.erb (0.9ms)
Rendered triggers/perform_actions/_record_an_event.html.erb (5.1ms)
Rendered layouts/_flash_errors.html.erb (0.6ms)
Rendered triggers/perform_actions/_unsubscribe.html.erb (1.4ms)
Rendered triggers/perform_actions/_send_notification_mail.html.erb (5.7ms)
Rendered triggers/trigger_details/_campaign.html.erb (2.2ms)
Rendered triggers/trigger_details/_apply_or_remove_tags.html.erb (1.2ms)
Rendered triggers/trigger_details/_form.html.erb (4.3ms)
Rendered triggers/trigger_details/_mail.html.erb (4.4ms)
Rendered triggers/trigger_details/_clicked_link.html.erb (1.0ms)
Rendered triggers/trigger_details/_visited_page.html.erb (0.9ms)
Rendered triggers/trigger_details/_update_custom_field.html.erb (0.8ms)
Rendered triggers/trigger/_tag.html.erb (1.0ms)
Rendered triggers/trigger/_campaign.html.erb (1.7ms)
Rendered triggers/trigger/_form.html.erb (2.1ms)
Rendered triggers/trigger/_link.html.erb (0.9ms)
Rendered triggers/trigger/_page.html.erb (0.8ms)
Rendered triggers/trigger/_email.html.erb (2.8ms)
Rendered triggers/trigger/_custom_field.html.erb (1.1ms)
Rendered triggers/actions/_add_tag_elements.html.erb (0.6ms)
Rendered triggers/actions/_tag.html.erb (2.7ms)
Rendered triggers/actions/_add_campaign_elements.html.erb (1.7ms)
Rendered triggers/actions/_campaign.html.erb (3.6ms)
Rendered triggers/actions/_add_multiple_campaigns_elements.html.erb (2.1ms)
Rendered triggers/actions/_multiple_campaigns.html.erb (4.1ms)
Rendered triggers/actions/_add_email_elements.html.erb (28.6ms)
Rendered triggers/actions/_email.html.erb (30.7ms)
Rendered triggers/actions/_add_custom_field_elements.html.erb (0.8ms)
Rendered triggers/actions/_custom_field.html.erb (3.2ms)
Rendered triggers/actions/_add_unsubscribe_elements.html.erb (0.7ms)
Rendered triggers/actions/_unsubscribe.html.erb (2.7ms)
Rendered triggers/actions/_notification_email.html.erb (0.9ms)
Rendered triggers/actions/_delete_subscriber.html.erb (0.5ms)
Rendered triggers/actions/_add_tag_elements.html.erb (0.6ms)
Rendered triggers/actions/_add_campaign_elements.html.erb (1.7ms)
Rendered triggers/actions/_add_multiple_campaigns_elements.html.erb (2.0ms)
Rendered triggers/actions/_add_email_elements.html.erb (2.4ms)
Rendered triggers/actions/_add_custom_field_elements.html.erb (0.8ms)
Rendered triggers/actions/_add_unsubscribe_elements.html.erb (0.7ms)
Rendered triggers/actions/_notification_email.html.erb (0.4ms)
Rendered triggers/_form.html.erb (804.3ms)
Rendered triggers/edit.html.erb within layouts/application (825.7ms)
Completed 200 OK in 1610ms (Views: 1562.3ms | ActiveRecord: 16.1ms)
It may slow down your application as rendering a partial takes some time, it may be very less time but it does take some time as rendering a partial invokes a render method so there is a second method call. It is totally on you, how you want the app's performance as it does reduce duplicate code and enhance code readibility
Related
Every time I add an image_tag to a page, the index is being rendered in the background (Rails 5)
I have a website with a large codebase. I noticed that every page that is rendered and have a picture on it, after rendering the page, it makes another request to the index and loading everything in the background. I have no idea why this happens. Started GET "/ganenet/main" for ::1 at 2022-08-11 12:41:13 +0300 Processing by OwnersController#main as HTML GanOwner Load (0.7ms) SELECT "gan_owners".* FROM "gan_owners" WHERE "gan_owners"."id" = $1 ORDER BY "gan_owners"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]] Rendering owners/main.haml within layouts/application Gan Load (0.4ms) SELECT "gans".* FROM "gans" WHERE "gans"."gan_owner_id" = $1 [["gan_owner_id", 1]] Rendered owners/main.haml within layouts/application (6.4ms) Rendered layouts/_google_tag_manager.haml (1.4ms) Rendered layouts/_mixpanel.haml (2.2ms) Rendered layouts/_hotjar.haml (1.9ms) Rendered shared/_intercom.haml (2.5ms) Rendered shared/_onesignal.html (0.3ms) Rendered shared/_staging_env.haml (2.4ms) Rendered shared/email_subscriptions/_consultant.html (0.4ms) Rendered shared/modals/_consultant.haml (3.1ms) Rendered shared/_modal.haml (8.5ms) Rendered shared/_header.haml (18.4ms) Rendered shared/owners/_navbar.haml (7.3ms) Rendered shared/_gtm.haml (2.2ms) Rendered shared/_modal.haml (11.5ms) Rendered shared/_modal.haml (4.2ms) Rendered shared/_modal.haml (57.8ms) Rendered shared/modals/_ganenet_lekan.haml (83.3ms) Rendered shared/_modal.haml (0.9ms) Rendered shared/modals/_thankyou_contact_soon.haml (3.4ms) Rendered shared/_modal.haml (0.5ms) Rendered shared/modals/_thankyou_generic.haml (3.0ms) Rendered shared/modals/_video_modal.haml (3.8ms) Rendered shared/_footer.haml (3.0ms) Rendered shared/_accessibility.html (0.2ms) Completed 200 OK in 254ms (Views: 246.9ms | ActiveRecord: 1.1ms) This is when the page I want is loaded, which is fine. But right after this, I get more requests which come out of nowhere. Started GET "/dist/instantsearch.min.js.map" for ::1 at 2022-08-11 12:41:13 +0300 Started GET "/" for ::1 at 2022-08-11 12:41:13 +0300 Processing by HomeController#index as HTML Started GET "/" for ::1 at 2022-08-11 12:41:13 +0300 Processing by HomeController#index as HTML And it loads a bunch of stuff from the database which are related to the homepage (which is HomeController#index. I noticed that the index loads only on pages that have at least one image on it. I couldn't find any info on this issue so far. Would be happy to hear from experienced folks with this issue.
Why is my rails app showing a blank page?
I am going though Michael Hartl's rails Tutorial chapter 10 section 10.2. And my rails app is now showing a blank page for all pages I try to load on the local host. I have tried resetting the computer as suggested in another post, but this didn't work. I have checked the development log and here is the error message. Started GET "/users/3" for 95.10.6.124 at 2017-11-05 16:36:43 +0000 Cannot render console from 95.10.6.124! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 Processing by UsersController#show as HTML Parameters: {"id"=>"3"} [1m[36mUser Load (0.2ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?[0m [["id", 3], ["LIMIT", 1]] Rendering users/show.html.erb within layouts/application Rendered users/show.html.erb within layouts/application (1.7ms) Rendered layouts/_rails_default.html.erb (27.1ms) Rendered layouts/_shim.html.erb (0.5ms) [1m[36mUser Load (0.2ms)[0m [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?[0m [["id", 3], ["LIMIT", 1]] Rendered layouts/_header.html.erb (2.3ms) Rendered layouts/_footer.html.erb (0.5ms) Completed 200 OK in 41ms (Views: 38.0ms | ActiveRecord: 0.4ms) This is strange as I undid the changes I made and now it doesnt work. In fact the serve doesnt seem to start. Instead of seeing the usual "ctrl+c to stop" at the end, the command prompt appears. This hasnt happened before and to my mnowledge I havent done anything differently. Could someone help me with this, thanks.
How do I debug what takes a partial to render so long in rails?
Rendered cars/_handover_instruction_fields.html.slim (5.5ms) Rendered cars/_handover_instruction_fields.html.slim (0.6ms) Rendered cars/_handover_instruction_fields.html.slim (0.5ms) Rendered cars/_handover_instruction_fields.html.slim (0.5ms) Rendered cars/_handover_instruction_fields.html.slim (0.5ms) Rendered cars/_handover_instruction_fields.html.slim (0.5ms) Rendered cars/_edit_handover.html.slim (30.7ms) Rendered cars/_edit_vrd.html.slim (5.2ms) Rendered cars/_edit_features.html.slim (3.5ms) Rendered cars/_edit_description.html.slim (5.2ms) CarPhoto Load (0.5ms) SELECT "car_photos".* FROM "car_photos" WHERE "car_photos"."car_id" = $1 [["car_id", 19]] Rendered cars/_photo_fields.html.slim (217.0ms) Rendered cars/_photo_fields.html.slim (1.5ms) Rendered cars/_photo_fields.html.slim (1.1ms) Rendered cars/_photo_fields.html.slim (1.1ms) Rendered cars/_photo_fields.html.slim (1.1ms) Rendered cars/_photo_fields.html.slim (1.0ms) Rendered cars/_photo_fields.html.slim (1.1ms) Rendered cars/_photo_fields.html.slim (1.0ms) Rendered cars/_edit_photos.html.slim (254.6ms) Rendered cars/_edit_js.html.erb (0.5ms) Rendered cars/edit.html.slim within layouts/application (356.7ms) Rendered shared/_flash.html.slim (5.5ms) Rendered shared/_slideout_nav.html.slim (16.9ms) Rendered svgs/_carshare_typeface_blue_small.html (0.8ms) Rendered shared/_header_nav.html.slim (20.1ms) Above is an excerpt of the Rails.logger when I render one of the pages in my webapp. I realised some of the partial takes suspciously long to render. For example Rendered cars/_photo_fields.html.slim (217.0ms) Rendered cars/_photo_fields.html.slim (1.5ms) I want to find out what makes the rendering so long and how i can improve it.
<% benchmark("Showing projects partial") do %> <%= render #projects %> <% end %> looks interesting. A tip in general, if you have many #items don't call render each time. This saves you time. #items.each do |item| render 'one_item', :item => item end Instead render one time with a collection for example.
Check your logs and it will show you the database queries being generated. This is usually the first place to look and it will highlight where you can make performance improvements by optimising your queries. The obvious one is to check if you can benefit from N + 1 queries using includes. There are other steps you can take as well, such as adding indices, using pluck if you only need to get individual attributes, using LIMIT and avoid sorting.
rails, when rendering a partial, each render outputs in the log. Is this a performance hit?
For example if looping over #feed, which renders a partial, you see the following in the log: Rendered feeds/_feed_item.html.erb (2.5ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (1.6ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (2.8ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (2.5ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.8ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (1.6ms) Rendered feeds/_feed_item.html.erb (1.3ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.2ms) Rendered feeds/_feed_item.html.erb (1.4ms) Rendered feeds/_feed_item.html.erb (1.5ms) Rendered feeds/_feed_item.html.erb (1.6ms) Is that a performance hit? Is there a better way to handle this so it doesn't output every time? Thanks
Yes, it's a performance hit. Render a collection.
Why is ActiveRecord issuing a separate query per join?
I'm doing an ActiveRecord find operation (via the "will_paginate" library) like this: contacts = Contact.paginate(:all, :conditions => conditions_specified, :select => "DISTINCT contacts.*", :joins => joins, :include => [:addresses, :emails, :phone_numbers, {:addresses => :organization}], :page => page, :per_page => ##PAGE_SIZE, :order => 'last_name, first_name, middle_name') In the console, I get the output shown below. By setting the include parameter, I expect this to result in only one query. But in the output I'm seeing many queries. For example, I'm surprised to see the line... Address Load (2.5ms) SELECT `addresses`.* FROM `addresses` WHERE (`addresses`.contact_id IN (94,106,104,108,121,55,40,75,62,4,67,36,77,64,7,35,24,68,57,117,8,30,85)) in the output below. (I understand that the SHOW FIELDS FROM queries are cached in production so that's not a problem. It's all the extra SELECTS I'm trying to figure out.) Processing ContactController#index (for 127.0.0.1 at 2009-01-03 21:21:18) [GET] Session ID: d453897c2f67c29c9a68d3fbc7b94f7b ContactSearch Columns (4.4ms) SHOW FIELDS FROM `contact_searches` Contact Load (1.1ms) SELECT DISTINCT contacts.* FROM `contacts` WHERE (contacts.last_name LIKE '%n%') ORDER BY last_name, first_name, middle_name LIMIT 0, 35 Contact Columns (2.3ms) SHOW FIELDS FROM `contacts` Address Load (2.5ms) SELECT `addresses`.* FROM `addresses` WHERE (`addresses`.contact_id IN (94,106,104,108,121,55,40,75,62,4,67,36,77,64,7,35,24,68,57,117,8,30,85)) Address Columns (2.7ms) SHOW FIELDS FROM `addresses` Email Load (1.7ms) SELECT `emails`.* FROM `emails` WHERE (`emails`.contact_id IN (94,106,104,108,121,55,40,75,62,4,67,36,77,64,7,35,24,68,57,117,8,30,85)) Email Columns (1.8ms) SHOW FIELDS FROM `emails` PhoneNumber Load (3.3ms) SELECT `phone_numbers`.* FROM `phone_numbers` WHERE (`phone_numbers`.contact_id IN (94,106,104,108,121,55,40,75,62,4,67,36,77,64,7,35,24,68,57,117,8,30,85)) PhoneNumber Columns (3.0ms) SHOW FIELDS FROM `phone_numbers` Organization Columns (2.9ms) SHOW FIELDS FROM `organizations` Organization Load (0.9ms) SELECT * FROM `organizations` WHERE (`organizations`.`id` IN (99,116,44,6,23,78,107,91,79,119,14,120,71,26,59,94,27,100,62,1,51,29,30,2,65,76,5)) Rendering template within layouts/main Rendering contact/index Rendered contact/_field_function_specifier (0.9ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_field_function_specifier (0.6ms) Rendered contact/_search_form (14.1ms) Rendered contact/_quick_view_contact_info (3.2ms) Rendered contact/_quick_view_contact_info (2.1ms) Rendered contact/_quick_view_contact_info (1.9ms) Rendered contact/_quick_view_contact_info (1.9ms) Rendered contact/_quick_view_contact_info (0.8ms) Rendered contact/_quick_view_contact_info (2.0ms) Rendered contact/_quick_view_contact_info (2.4ms) Rendered contact/_quick_view_contact_info (1.7ms) Rendered contact/_quick_view_contact_info (1.4ms) Rendered contact/_quick_view_contact_info (1.7ms) Rendered contact/_quick_view_contact_info (2.2ms) Rendered contact/_quick_view_contact_info (1.5ms) Rendered contact/_quick_view_contact_info (2.0ms) Rendered contact/_quick_view_contact_info (1.7ms) Rendered contact/_quick_view_contact_info (1.8ms) Rendered contact/_quick_view_contact_info (3.6ms) Rendered contact/_quick_view_contact_info (2.2ms) Rendered contact/_quick_view_contact_info (2.2ms) Rendered contact/_quick_view_contact_info (1.9ms) Rendered contact/_quick_view_contact_info (1.7ms) Rendered contact/_quick_view_contact_info (2.0ms) Rendered contact/_quick_view_contact_info (2.1ms) Rendered contact/_quick_view_contact_info (1.9ms) Completed in 308ms (View: 104, DB: 27) | 200 OK [http://localhost/contact]
I did a little more research and found the answer. I'm updating this for those who search later. The long answer is in this blog post. It appears that when you do a find that has both joins and a limit, ActiveRecord has to first query the main table to get the IDs of the rows to return, then redo the query using just the IDs in order to apply the limit. Since I was using will_paginate, that's what happened as will_paginate used limited queries to do the pagination.