Skip to content

Commit

Permalink
Use frozen string literals and regex constants to reduce allocations
Browse files Browse the repository at this point in the history
When doing operations on lots of models, strip_attributes can be responsible for a lot
of small allocations for strings and regexes that do not change, but are nonetheless
re-allocated every time a model is saved. Across thousands of records, this is a sizeable
chunk of memory. Luckily, since the strings and regexes do not change, we can mark them as
frozen and/or reference them via constants to avoid allocating them more than once.
  • Loading branch information
maxfierke committed May 24, 2022
1 parent 53c573b commit e95ef61
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions lib/strip_attributes.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# frozen_string_literal: true
require "active_model"

module ActiveModel::Validations::HelperMethods
Expand Down Expand Up @@ -27,8 +28,11 @@ module StripAttributes
# U+FEFF ZERO WIDTH NO-BREAK SPACE
MULTIBYTE_WHITE = "\u180E\u200B\u200C\u200D\u2060\uFEFF".freeze
MULTIBYTE_SPACE = /[[:space:]#{MULTIBYTE_WHITE}]/.freeze
MULTIBYTE_SPACE_AT_ENDS = /\A#{MULTIBYTE_SPACE}+|#{MULTIBYTE_SPACE}+\z/.freeze
MULTIBYTE_BLANK = /[[:blank:]#{MULTIBYTE_WHITE}]/.freeze
MULTIBYTE_BLANK_REPEATED = /#{MULTIBYTE_BLANK}+/.freeze
MULTIBYTE_SUPPORTED = "\u0020" == " "
NEWLINES = /[\r\n]+/.freeze

def self.strip(record_or_string, options = {})
if record_or_string.respond_to?(:attributes)
Expand Down Expand Up @@ -62,16 +66,16 @@ def self.strip_string(value, options = {})
value.gsub!(regex, "") if regex

if MULTIBYTE_SUPPORTED && Encoding.compatible?(value, MULTIBYTE_SPACE)
value.gsub!(/\A#{MULTIBYTE_SPACE}+|#{MULTIBYTE_SPACE}+\z/, "")
value.gsub!(MULTIBYTE_SPACE_AT_ENDS, "")
else
value.strip!
end

value.gsub!(/[\r\n]+/, " ") if replace_newlines
value.gsub!(NEWLINES, " ") if replace_newlines

if collapse_spaces
if MULTIBYTE_SUPPORTED && Encoding.compatible?(value, MULTIBYTE_BLANK)
value.gsub!(/#{MULTIBYTE_BLANK}+/, " ")
value.gsub!(MULTIBYTE_BLANK_REPEATED, " ")
else
value.squeeze!(" ")
end
Expand Down

0 comments on commit e95ef61

Please sign in to comment.