From e95ef61b384245f29c3fc0a499dffb0dd099e1c7 Mon Sep 17 00:00:00 2001 From: Max Fierke Date: Tue, 24 May 2022 10:16:26 -0500 Subject: [PATCH] Use frozen string literals and regex constants to reduce allocations 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. --- lib/strip_attributes.rb | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/strip_attributes.rb b/lib/strip_attributes.rb index 2eabafb..e642041 100644 --- a/lib/strip_attributes.rb +++ b/lib/strip_attributes.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "active_model" module ActiveModel::Validations::HelperMethods @@ -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) @@ -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