From 9a959a0c454448353d2d9c00511a353f874d8d9d Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Mon, 15 Apr 2019 15:01:12 -0700 Subject: [PATCH] Avoid string allocations in BacktraceCleaner Our backtraces tend to be fairly large so this operates over quite a few strings. Previously, each filter would call `String#sub`, which always returns a new string object, and uses a new string buffer any time it modifies the string. String#slice allows Ruby to share the same internal string buffer, which should be faster and use less memory. In cases where changes aren't necessary we can also reuse the same string object. This should not change behaviour except for the last filter which changes from sub(/\.\//, "") to sub(/\A\.\//, ""), which I think was the original intention. --- railties/lib/rails/backtrace_cleaner.rb | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/railties/lib/rails/backtrace_cleaner.rb b/railties/lib/rails/backtrace_cleaner.rb index 7c2eb1dc42..6ac963e1ef 100644 --- a/railties/lib/rails/backtrace_cleaner.rb +++ b/railties/lib/rails/backtrace_cleaner.rb @@ -4,18 +4,25 @@ require "active_support/backtrace_cleaner" module Rails class BacktraceCleaner < ActiveSupport::BacktraceCleaner - APP_DIRS_PATTERN = /^\/?(app|config|lib|test|\(\w*\))/ + APP_DIRS_PATTERN = /\A\/?(?:app|config|lib|test|\(\w*\))/ RENDER_TEMPLATE_PATTERN = /:in `.*_\w+_{2,3}\d+_\d+'/ - EMPTY_STRING = "" - SLASH = "/" - DOT_SLASH = "./" def initialize super @root = "#{Rails.root}/" - add_filter { |line| line.sub(@root, EMPTY_STRING) } - add_filter { |line| line.sub(RENDER_TEMPLATE_PATTERN, EMPTY_STRING) } - add_filter { |line| line.sub(DOT_SLASH, SLASH) } # for tests + add_filter do |line| + line.start_with?(@root) ? line.from(@root.size) : line + end + add_filter do |line| + if RENDER_TEMPLATE_PATTERN.match?(line) + line.sub(RENDER_TEMPLATE_PATTERN, "") + else + line + end + end + add_filter do |line| + line.start_with?("./") ? line.from(1) : line + end add_silencer { |line| !APP_DIRS_PATTERN.match?(line) } end end