-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
In `apply_inflections` a string is down cased and some whitespace stripped in the front (which allocate strings). This would normally be fine, however `uncountables` is a fairly small array (10 elements out of the box) and this method gets called a TON. Instead we can keep an array of valid regexes for each uncountable so we don't have to allocate new strings. This change buys us 325,106 bytes of memory and 3,251 fewer objects per request.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,14 +27,45 @@ module Inflector | |
class Inflections | ||
@__instance__ = ThreadSafe::Cache.new | ||
|
||
class Uncountables < Array | ||
def initialize | ||
@regex_array = [] | ||
super | ||
end | ||
|
||
def delete(entry) | ||
super entry | ||
@regex_array.delete(to_regex(entry)) | ||
end | ||
|
||
def <<(*word) | ||
add(word) | ||
end | ||
|
||
def add(words) | ||
self.concat(words.flatten.map(&:downcase)) | ||
@regex_array += self.map {|word| to_regex(word) } | ||
self | ||
end | ||
|
||
def uncountable?(str) | ||
@regex_array.detect {|regex| regex.match(str) } | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
schneems
Author
Owner
|
||
end | ||
|
||
private | ||
def to_regex(string) | ||
/\b#{::Regexp.escape(string)}\Z/i | ||
end | ||
end | ||
|
||
def self.instance(locale = :en) | ||
@__instance__[locale] ||= new | ||
end | ||
|
||
attr_reader :plurals, :singulars, :uncountables, :humans, :acronyms, :acronym_regex | ||
|
||
def initialize | ||
@plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], [], [], {}, /(?=a)b/ | ||
@plurals, @singulars, @uncountables, @humans, @acronyms, @acronym_regex = [], [], Uncountables.new, [], {}, /(?=a)b/ | ||
end | ||
|
||
# Private, for the test suite. | ||
|
@@ -160,7 +191,7 @@ def irregular(singular, plural) | |
# uncountable 'money', 'information' | ||
# uncountable %w( money information rice ) | ||
def uncountable(*words) | ||
@uncountables += words.flatten.map(&:downcase) | ||
@uncountables.add(words) | ||
end | ||
|
||
# Specifies a humanized form of a string by a regular expression rule or | ||
|
@@ -185,7 +216,7 @@ def human(rule, replacement) | |
def clear(scope = :all) | ||
case scope | ||
when :all | ||
@plurals, @singulars, @uncountables, @humans = [], [], [], [] | ||
@plurals, @singulars, @uncountables, @humans = [], [], Uncountables.new, [] | ||
else | ||
instance_variable_set "@#{scope}", [] | ||
end | ||
|
( I hope you don't mind me commenting here.)
You can avoid creating the MatchData object by using
[]
or=~
onstr
and passing itregex
.@regex_array.detect { |regex| str[regex] }
or@regex_array.detect { |regex| str =~ regex }
Also
any?
seems more appropriate thandetect
. Is there a reason to usedetect
?