From dacbbb86fab301d47a7c25df0746223de4acd06b Mon Sep 17 00:00:00 2001 From: Peter Bhat Harkins Date: Wed, 23 Aug 2023 09:30:27 -0500 Subject: [PATCH] heinous_inline_partial for story show perf --- app/controllers/application_controller.rb | 7 +- app/views/stories/show.html.erb | 170 +++++++++++++++++- config/initializers/heinous_inline_partial.rb | 50 ++++++ 3 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 config/initializers/heinous_inline_partial.rb diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index b30070ef..5415ae06 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -3,9 +3,10 @@ class ApplicationController < ActionController::Base protect_from_forgery before_action :authenticate_user + before_action :heinous_inline_partials, if: -> { Rails.env.development? } before_action :mini_profiler - before_action :set_traffic_style before_action :prepare_exception_notifier + before_action :set_traffic_style # match this in your nginx config for bypassing the file cache TAG_FILTER_COOKIE = :tag_filters @@ -72,6 +73,10 @@ class ApplicationController < ActionController::Base ) end + def heinous_inline_partials + do_heinous_inline_partial_replacement + end + def mini_profiler if @user && @user.is_admin? Rack::MiniProfiler.authorize_request diff --git a/app/views/stories/show.html.erb b/app/views/stories/show.html.erb index bebe8d4f..087c3cc7 100644 --- a/app/views/stories/show.html.erb +++ b/app/views/stories/show.html.erb @@ -56,12 +56,170 @@ <% end %> <% previous_depth = comment.depth %> - <%= render "comments/comment", :comment => comment, - :show_story => (comment.story_id != @story.id), - :show_tree_lines => true, - :was_merged => (comment.story_id != @story.id), - :children => [], - :is_unread => is_unread?(comment) %> + <% + show_story = (comment.story_id != @story.id) + show_tree_lines = true + was_merged = (comment.story_id != @story.id) + is_unread = is_unread?(comment) + %> +<%#heinous_inline_partial(comments/_comment.html.erb)%> +<%# Do not edit, the content until /heinous_inline_partial comes from the named partial %> +<% flagged = comment.current_vote && comment.current_vote[:vote] == -1 %> + Comment::COLLAPSE_SCORE && !flagged) ? "" : "checked" %>> + +
+ <%= comment.score < Comment::SCORE_RANGE_TO_HIDE.first ? "bad" : "" %>"> + + <% if defined?(show_tree_lines) && show_tree_lines %> + + <% end %> + + <% if !comment.is_gone? %> + <% can_flag = @user && @user.can_flag?(comment) %> + <% score_display = comment.score_for_user(@user) %> +
+ <% if @user %> + + <% else %> + <%= link_to "", login_path, :class => "upvoter" %> + <% end %> +
<%= score_display %>
+
+
+ <%= score_display != " " ? "score_shown" : "" %> + <%= defined?(children) && children ? "" : "no_children" %>">
+ <% end %> + +
+ +
+ <% if comment.is_gone? %> +

+ + [<%= comment.gone_text %><% if @user && @user.is_moderator? %> Visible to moderator:<% end %>] + +

+ <% if @user && @user.is_moderator? %> + <%= raw comment.markeddown_comment %> + <% end %> + <% else %> + <%= raw comment.markeddown_comment %> + <% end %> +
+
+
+ +<%#/heinous_inline_partial(comments/_comment.html.erb)%> +%> +%> <%# # If you edit this structure, update the incredibly brittle css selector diff --git a/config/initializers/heinous_inline_partial.rb b/config/initializers/heinous_inline_partial.rb new file mode 100644 index 00000000..8b24a49e --- /dev/null +++ b/config/initializers/heinous_inline_partial.rb @@ -0,0 +1,50 @@ +# Inlines partials into parent templates for performance. +# In production & test: once at startup; development: every request +# +# Inlining the comments/_comment partial into stories/show (bulk of our traffic!) +# gives a 25% speedup over 'render collection: @comment'. + +HEINOUS_INLINE_PARTIALS = { + # including template => partial +} + +Dir['app/views/**/*.erb'].each do |filename| + template = File.read(filename) + next unless template.include? 'heinous_inline_partial' + + partial_match = template.match(/^<%#heinous_inline_partial\(([\w\/\.]+)\)%>/) + partial_name = partial_match && partial_match.captures.first + HEINOUS_INLINE_PARTIALS[filename] = 'app/views/' + partial_name +end +l = Logger.new(STDOUT) +l.warn "heinous_inline_partial initialized, found: #{HEINOUS_INLINE_PARTIALS}" + +def do_heinous_inline_partial_replacement + HEINOUS_INLINE_PARTIALS.each do |filename, partial_name| + partial_mtime = File.mtime(partial_name) + # puts "heinous contemplating #{filename} #{File.mtime(filename).to_i} #{partial_mtime.to_i}" + next if File.mtime(filename) == partial_mtime + # puts " will replace in #{filename}" + + template = File.read(filename) + template.sub!(/^<%#heinous_inline_partial\(([\w\/\.]+)\)%>(.+)^<%#\/heinous_inline_partial\(([\w\/\.]+)\)/m) { |match| + raise "Template name didn't match in open and closing tags. One per file!" unless $1 == $3 + # puts " .sub! matched, replacing" + + <<~REPLACE + <%#heinous_inline_partial(#{$1})%> + <%# Do not edit, the content until /heinous_inline_partial comes from the named partial %> + #{File.read(partial_name)} + <%#/heinous_inline_partial(#{$1})%> + REPLACE + } + # puts " writing filename #{filename}" + File.write(filename, template) + File.utime(partial_mtime, partial_mtime, filename) + end +end + +# run once at startup: +do_heinous_inline_partial_replacement + +# see before_action in ApplicationController for development mode hook