Skip to content

Commit

Permalink
Memory optimization
Browse files Browse the repository at this point in the history
`regexes.yaml` contains quite a lot of duplicated strings.
By passing `freeze: true` to `YAML.load` we allow the parser to deduplicate them.

Additionally, the regexes source and flags are never used, so they
can be removed from the long lived hashes.

Before:
```
Total allocated: 3.47 MB (28214 objects)
Total retained: 1.45 MB (8422 objects)
```

After:
```
Total allocated: 3.71 MB (30218 objects)
Total retained: 1.24 MB (4583 objects)
```

It's not a big difference in size, but it cuts down in half the number
of objects than need to be marked by the GC.
  • Loading branch information
byroot committed Jul 7, 2022
1 parent c24a36d commit b050eef
Showing 1 changed file with 16 additions and 8 deletions.
24 changes: 16 additions & 8 deletions lib/user_agent_parser/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,24 @@ def parse(user_agent)
private

def load_patterns(path)
yml = YAML.load_file(path)

# Parse all the regexs
yml.each_pair do |_type, patterns|
patterns.each do |pattern|
pattern[:regex] = Regexp.new(pattern['regex'], pattern['regex_flag'] == 'i')
end
yml = begin
YAML.load_file(path, freeze: true)
rescue ArgumentError
YAML.load_file(path)
end
[
parse_pattern(yml['user_agent_parsers']),
parse_pattern(yml['os_parsers']),
parse_pattern(yml['device_parsers']),
]
end

[yml['user_agent_parsers'], yml['os_parsers'], yml['device_parsers']]
def parse_pattern(patterns)
patterns.map do |pattern|
pattern = pattern.dup
pattern[:regex] = Regexp.new(pattern.delete('regex'), pattern.delete('regex_flag') == 'i')
pattern
end
end

def parse_ua(user_agent, os = nil, device = nil)
Expand Down

0 comments on commit b050eef

Please sign in to comment.