From 2a4d4301d405dbc4a6bce85b4632a78099c8d1c6 Mon Sep 17 00:00:00 2001 From: schneems Date: Fri, 24 Jul 2015 23:35:18 -0500 Subject: Decrease string allocation in content_tag_string When an unknonwn key is passed to the hash in `PRE_CONTENT_STRINGS` it returns nil, when you call "#{nil}" it allocates a new empty string. We can get around this allocation by using a default value `Hash.new { "".freeze }`. We can avoid the `to_sym` call by pre-populating the hash with a symbol key in addition to a string key. We can freeze some strings when using Array#* to reduce allocations. Array#join can take frozen strings. This change buys us 86,600 bytes of memory and 1,857 fewer objects per request. --- actionview/lib/action_view/helpers/tag_helper.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'actionview') diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb index a87c223a71..a821bd9543 100644 --- a/actionview/lib/action_view/helpers/tag_helper.rb +++ b/actionview/lib/action_view/helpers/tag_helper.rb @@ -22,9 +22,10 @@ module ActionView TAG_PREFIXES = ['aria', 'data', :aria, :data].to_set - PRE_CONTENT_STRINGS = { - :textarea => "\n" - } + PRE_CONTENT_STRINGS = Hash.new { "".freeze } + PRE_CONTENT_STRINGS[:textarea] = "\n" + PRE_CONTENT_STRINGS["textarea"] = "\n" + # Returns an empty HTML tag of type +name+ which by default is XHTML # compliant. Set +open+ to true to create an open tag compatible @@ -143,7 +144,7 @@ module ActionView def content_tag_string(name, content, options, escape = true) tag_options = tag_options(options, escape) if options content = ERB::Util.unwrapped_html_escape(content) if escape - "<#{name}#{tag_options}>#{PRE_CONTENT_STRINGS[name.to_sym]}#{content}".html_safe + "<#{name}#{tag_options}>#{PRE_CONTENT_STRINGS[name]}#{content}".html_safe end def tag_options(options, escape = true) @@ -160,7 +161,7 @@ module ActionView attrs << tag_option(key, value, escape) end end - " #{attrs * ' '}" unless attrs.empty? + " ".freeze + attrs * ' '.freeze unless attrs.empty? end def prefix_tag_option(prefix, key, value, escape) @@ -177,7 +178,7 @@ module ActionView def tag_option(key, value, escape) if value.is_a?(Array) - value = escape ? safe_join(value, " ") : value.join(" ") + value = escape ? safe_join(value, " ".freeze) : value.join(" ".freeze) else value = escape ? ERB::Util.unwrapped_html_escape(value) : value end -- cgit v1.2.3 From 2e95d2ef90a32a7ed6fbb14f4e0a6764fc9e017b Mon Sep 17 00:00:00 2001 From: schneems Date: Fri, 24 Jul 2015 23:41:25 -0500 Subject: Optimize hash key No idea why on earth this hash key isn't already optimized by MRI, but it isn't. :shit: This change buys us 74,077 bytes of memory and 1,852 fewer objects per request. --- actionview/lib/action_view/helpers/url_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionview') diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb index 7d92651183..5eb1377d38 100644 --- a/actionview/lib/action_view/helpers/url_helper.rb +++ b/actionview/lib/action_view/helpers/url_helper.rb @@ -184,7 +184,7 @@ module ActionView html_options = convert_options_to_data_attributes(options, html_options) url = url_for(options) - html_options['href'] ||= url + html_options["href".freeze] ||= url content_tag(:a, name || url, html_options, &block) end -- cgit v1.2.3 From 9b189a31696b6572ffb8164f1f3041d57e8eeebe Mon Sep 17 00:00:00 2001 From: schneems Date: Sat, 25 Jul 2015 00:08:47 -0500 Subject: Cut string ActionView template allocations The instrument method creates new strings, the most common action to instrument is "!render_template` so we can detect when that action is occurring and use a frozen string instead. This change buys us 113,714 bytes of memory and 1,790 fewer objects per request. --- actionview/lib/action_view/template.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'actionview') diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb index 1ce9f94b13..e232808dcb 100644 --- a/actionview/lib/action_view/template.rb +++ b/actionview/lib/action_view/template.rb @@ -154,7 +154,7 @@ module ActionView # we use a bang in this instrumentation because you don't want to # consume this in production. This is only slow if it's being listened to. def render(view, locals, buffer=nil, &block) - instrument("!render_template") do + instrument("!render_template".freeze) do compile!(view) view.send(method_name, locals, buffer, &block) end @@ -348,7 +348,12 @@ module ActionView def instrument(action, &block) payload = { virtual_path: @virtual_path, identifier: @identifier } - ActiveSupport::Notifications.instrument("#{action}.action_view", payload, &block) + case action + when "!render_template".freeze + ActiveSupport::Notifications.instrument("!render_template.action_view".freeze, payload, &block) + else + ActiveSupport::Notifications.instrument("#{action}.action_view".freeze, payload, &block) + end end EXPLICIT_COLLECTION = /# Template Collection: (?\w+)/ -- cgit v1.2.3 From e76a84350595ca6772d3c00f456b35e411fba6c1 Mon Sep 17 00:00:00 2001 From: schneems Date: Sat, 25 Jul 2015 00:18:13 -0500 Subject: Cut string allocations in content_tag_string content_tag's first argument is will generate a string with an html tag so `:a` will generate: ``. When this happens, the symbol is implicitly `to_s`-d so a new string is allocated. We can get around that by using a frozen string instead which This change buys us 74,236 bytes of memory and 1,855 fewer objects per request. --- actionview/lib/action_view/helpers/asset_tag_helper.rb | 2 +- actionview/lib/action_view/helpers/date_helper.rb | 12 ++++++------ actionview/lib/action_view/helpers/form_options_helper.rb | 8 ++++---- actionview/lib/action_view/helpers/form_tag_helper.rb | 8 ++++---- actionview/lib/action_view/helpers/javascript_helper.rb | 6 +++--- actionview/lib/action_view/helpers/url_helper.rb | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) (limited to 'actionview') diff --git a/actionview/lib/action_view/helpers/asset_tag_helper.rb b/actionview/lib/action_view/helpers/asset_tag_helper.rb index 3041ad3ef7..e506c782d6 100644 --- a/actionview/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionview/lib/action_view/helpers/asset_tag_helper.rb @@ -60,7 +60,7 @@ module ActionView tag_options = { "src" => path_to_javascript(source, path_options) }.merge!(options) - content_tag(:script, "", tag_options) + content_tag("script".freeze, "", tag_options) }.join("\n").html_safe end diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb index fbd7261477..94fbaa2dca 100644 --- a/actionview/lib/action_view/helpers/date_helper.rb +++ b/actionview/lib/action_view/helpers/date_helper.rb @@ -681,7 +681,7 @@ module ActionView content = args.first || I18n.l(date_or_time, :format => format) datetime = date_or_time.acts_like?(:time) ? date_or_time.xmlschema : date_or_time.iso8601 - content_tag(:time, content, options.reverse_merge(:datetime => datetime), &block) + content_tag("time".freeze, content, options.reverse_merge(:datetime => datetime), &block) end end @@ -809,7 +809,7 @@ module ActionView 1.upto(12) do |month_number| options = { :value => month_number } options[:selected] = "selected" if month == month_number - month_options << content_tag(:option, month_name(month_number), options) + "\n" + month_options << content_tag("option".freeze, month_name(month_number), options) + "\n" end build_select(:month, month_options.join) end @@ -971,7 +971,7 @@ module ActionView tag_options[:selected] = "selected" if selected == i text = options[:use_two_digit_numbers] ? sprintf("%02d", i) : value text = options[:ampm] ? AMPM_TRANSLATION[i] : text - select_options << content_tag(:option, text, tag_options) + select_options << content_tag("option".freeze, text, tag_options) end (select_options.join("\n") + "\n").html_safe @@ -991,11 +991,11 @@ module ActionView select_options[:class] = [select_options[:class], type].compact.join(' ') if @options[:with_css_classes] select_html = "\n" - select_html << content_tag(:option, '', :value => '') + "\n" if @options[:include_blank] + select_html << content_tag("option".freeze, '', :value => '') + "\n" if @options[:include_blank] select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt] select_html << select_options_as_html - (content_tag(:select, select_html.html_safe, select_options) + "\n").html_safe + (content_tag("select".freeze, select_html.html_safe, select_options) + "\n").html_safe end # Builds a prompt option tag with supplied options or from default options. @@ -1012,7 +1012,7 @@ module ActionView I18n.translate(:"datetime.prompts.#{type}", :locale => @options[:locale]) end - prompt ? content_tag(:option, prompt, :value => '') : '' + prompt ? content_tag("option".freeze, prompt, :value => '') : '' end # Builds hidden input tag for date part and value. diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index 8e729b3c39..728e633bbf 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -456,7 +456,7 @@ module ActionView option_tags = options_from_collection_for_select( group.send(group_method), option_key_method, option_value_method, selected_key) - content_tag(:optgroup, option_tags, label: group.send(group_label_method)) + content_tag("optgroup".freeze, option_tags, label: group.send(group_label_method)) end.join.html_safe end @@ -528,7 +528,7 @@ module ActionView body = "".html_safe if prompt - body.safe_concat content_tag(:option, prompt_text(prompt), value: "") + body.safe_concat content_tag("option".freeze, prompt_text(prompt), value: "") end grouped_options.each do |container| @@ -541,7 +541,7 @@ module ActionView end html_attributes = { label: label }.merge!(html_attributes) - body.safe_concat content_tag(:optgroup, options_for_select(container, selected_key), html_attributes) + body.safe_concat content_tag("optgroup".freeze, options_for_select(container, selected_key), html_attributes) end body @@ -577,7 +577,7 @@ module ActionView end zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected) - zone_options.safe_concat content_tag(:option, '-------------', value: '', disabled: true) + zone_options.safe_concat content_tag("option".freeze, '-------------', value: '', disabled: true) zone_options.safe_concat "\n" zones = zones - priority_zones diff --git a/actionview/lib/action_view/helpers/form_tag_helper.rb b/actionview/lib/action_view/helpers/form_tag_helper.rb index 896020bc15..d36701955a 100644 --- a/actionview/lib/action_view/helpers/form_tag_helper.rb +++ b/actionview/lib/action_view/helpers/form_tag_helper.rb @@ -140,15 +140,15 @@ module ActionView end if include_blank - option_tags = content_tag(:option, include_blank, value: '').safe_concat(option_tags) + option_tags = content_tag("option".freeze, include_blank, value: '').safe_concat(option_tags) end end if prompt = options.delete(:prompt) - option_tags = content_tag(:option, prompt, value: '').safe_concat(option_tags) + option_tags = content_tag("option".freeze, prompt, value: '').safe_concat(option_tags) end - content_tag :select, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys) + content_tag "select".freeze, option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys) end # Creates a standard text field; use these text fields to input smaller chunks of text like a username @@ -568,7 +568,7 @@ module ActionView # # =>

def field_set_tag(legend = nil, options = nil, &block) output = tag(:fieldset, options, true) - output.safe_concat(content_tag(:legend, legend)) unless legend.blank? + output.safe_concat(content_tag("legend".freeze, legend)) unless legend.blank? output.concat(capture(&block)) if block_given? output.safe_concat("") end diff --git a/actionview/lib/action_view/helpers/javascript_helper.rb b/actionview/lib/action_view/helpers/javascript_helper.rb index e237a32cb7..ed7e882c94 100644 --- a/actionview/lib/action_view/helpers/javascript_helper.rb +++ b/actionview/lib/action_view/helpers/javascript_helper.rb @@ -47,8 +47,8 @@ module ActionView # tag. # # javascript_tag "alert('All is good')", defer: 'defer' - # - # Returns: + # + # Returns: #