7

I'm creating a website that has a huge amount of HTML (many thousands of div elements). There's no real way to get away from having all these div elements and it's making the site load very slow (7-12 seconds). I've tried putting caching on the site, but it doesn't help, since the site still has to render all these div elements.

More specifically it's 140 dropdowns, that each contain 100-800 div elements and they take a long time to show.

My thoughts, was to render the div elements that are inside the dropdowns, after the page loads, but I don't know how to go about that?

What is the easiest way to render some of your partials AFTER the page has loaded? I'm using Rails 4 btw.

Any other suggestions on how to deal with HUGE amounts of HTML?

Holger Sindbaek
  • 2,278
  • 6
  • 41
  • 68
  • 4
    if you have 140 dropdowns, how do you expect the user to manage this? at least you might have these dropdowns split into sections, right? in this case you can load each section on demand. – akonsu Jan 19 '15 at 16:38
  • 2
    It certainly sounds like a large portion of the slowdown is simply your poor browser actually drawing all of this, in which case there is very little you can do other than simplify your design. – Octopoid Jan 19 '15 at 16:41
  • 2
    Do you must show all this element at the same time? Try using AJAX and show the elements only if they are needed.. – Grych Jan 19 '15 at 16:41
  • I need to render all the information in the dropdowns, so you can search all the dropdowns live (with JS). I know this sound a bit retarded, but that's how it is. Any other case, it would be a poor design decision with this many html elements, but it's needed here. How would you load the elements into the dropdowns after pageload on Rails? I've looked into some UJS, but not sure it's the right place to look? – Holger Sindbaek Jan 19 '15 at 16:46
  • 2
    "Any other case, it would be a poor design decision" - take a step back and re-read this. :) – Octopoid Jan 19 '15 at 16:47
  • @Octopoid Some time you have to go against what is usually considered a poor decision, because the design demands it. I don't enjoy rendering thousands of HTML elements, but the design demands it. Do you have a good solution to how I can do it with AJAX? – Holger Sindbaek Jan 19 '15 at 16:55
  • Assuming for a moment you do have the unique system requirement where presenting an actual human with 140 separate drop downs is the best way forward - yeah, AJAX is probably the way. Just load one thing after another, and include a loading spinner until it's done. It won't be any quicker in the end, but it'll at least feel a bit more responsive. – Octopoid Jan 19 '15 at 16:57

2 Answers2

3

I have a similar issue on one of my pages. Here are some things to try related to the select boxes.

(The top two may not be relevant since you said you tried caching, but I'm including for completeness. What type of caching did you try? How did you verify it was the browser rendering that was slow?)

Double check the cause of the problem

Comment out the code that generates the select boxes and check whether the time in your rails logs (as opposed to your browser measurements) drops. This establishes your "lower bound" for performance improvements on that measure.

Avoid using rails helpers.

If you're using select_tag, options_for_select, or any of that family of methods you may be doing a lot of repeated work since each time they are called they need to rebuild the list of options. If the options are the same for each select box, you can build them up once then just dump them in the page:

<% options = options_from_collection_for_select(@array, "id", "name") %>
<%= select_tag "myfield", options %>

If you need different selected values for each, you can try:

  1. Processing options after creation to add them. This is pretty gross and possibly won't give you much speed up over the default generators.
  2. Dump the defaults into a javascript variable, then set them with JS after the page loads.

AJAX in partials

This will give the illusion of loading faster, even though server time is the same (though it may be parallelized somewhat, you add extra network delay). The easiest way to do this is with jQuery's .load method.

$("#element-1").load("/path/to/partial/1")

Generate select boxes in JS

If you can get all the data you need to the client relatively fast (maybe serve it up in a JSON endpoint?) you can try building up the select boxes directly with jQuery, which is covered in Programmatically create select list

Remove redundant HTML

Why do your dropdowns have divs inside them? Is there a way to simplify?

Community
  • 1
  • 1
Xavier Shay
  • 4,067
  • 1
  • 30
  • 54
  • Thanks a lot for the elaborate answer. Right now I'm doing action caching (basically caching the whole page). I also tried fragment caching and query caching (but it's not the query that's slow). The thing that keeps seeming weird to me, is that in the local environment, the html/css renders really fast, so all the dropdowns load straight away, where in production, you can literally see each dropdown being added to the page with a 0,5 second delay after each other. Can you link to somewhere that has an example of using jQuery's load to create partials in Rails? – Holger Sindbaek Jan 19 '15 at 18:04
  • That's weird that you get different behaviour between dev/prod ... especially it being *faster* in dev! There are a few examples of using load here on SO: http://stackoverflow.com/questions/6701623/how-to-asynchronously-load-a-partial-page-in-rails, http://stackoverflow.com/questions/19129285/jquery-ajax-render-partial-with-rails-view, http://stackoverflow.com/questions/15694554/dynamically-render-view-in-a-partial-with-rails-and-jquery including one hacky trick I hadn't considered: rendering an ERB with the JS to execute. (fwiw these were top hits for google "rails jquery load partial") – Xavier Shay Jan 19 '15 at 18:38
  • have you tried using different browsers? Do they all exhibit the same problem? – Xavier Shay Jan 19 '15 at 18:38
  • Seems like it. I'll have a look at it jQuery. I think I would like to render an ERB with JS. – Holger Sindbaek Jan 19 '15 at 18:52
0

Although the question is few years old, maybe someone will benefit from this one.

1) in controller:

@companies = Company.all.pluck(:name, :id) #order is important here

2) in view:

<%= f.select(:company_id, options_for_select(
             @companies, selected: @user.company_id
             ), {}, class:"form-control m-b") %>

pluck grabs only :name, :id values, array of arrays, e.g,

=> [["Sumptus xiphias canto.", 5], ["My First Co.", 1]]

is created and then options_for_select populates options.

My 5000 records are populated in ~300ms in AJAX modal window. Not super fast, however I don't think regular user would complain.

matiss
  • 747
  • 15
  • 36