erb.rb: Skip creating regexp

if stags and etags are not changed from default.

:putobject insn (of regexp) will be used instead of :toregexp insn.
This means that the regexp won't be compiled for every
`SimpleScanner#scan` call.

It may not be a good idea to apply this kind of optimization for all cases.
But I applied this because it is default scanner and used frequently and has
relatively large impact for benchmark like this:

* Before
app_erb 1.023

* After
app_erb 0.781

This commit fixes only the bottleneck of performance regression introduced
in r53412. For maintainability, I won't fix other small regressions like
additional overhead of method calls.

[ruby-core:73820] [Bug #12074]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58842 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
k0kubun 2017-05-22 03:56:16 +00:00
parent 7a14ffbf5d
commit 72fb1e1690

View File

@ -371,11 +371,13 @@ class ERB
klass.new(src, trim_mode, percent)
end
DEFAULT_STAGS = %w(<%% <%= <%# <%).freeze
DEFAULT_ETAGS = %w(%%> %>).freeze
def initialize(src, trim_mode, percent)
@src = src
@stag = nil
@stags = %w(<%% <%= <%# <%).freeze
@etags = %w(%%> %>).freeze
@stags = DEFAULT_STAGS
@etags = DEFAULT_ETAGS
end
attr_accessor :stag
attr_reader :stags, :etags
@ -505,8 +507,8 @@ class ERB
else
class SimpleScanner < Scanner # :nodoc:
def scan
stag_reg = /(.*?)(#{stags.join('|')}|\z)/m
etag_reg = /(.*?)(#{etags.join('|')}|\z)/m
stag_reg = (stags == DEFAULT_STAGS) ? /(.*?)(<%[%=#]?|\z)/m : /(.*?)(#{stags.join('|')}|\z)/m
etag_reg = (etags == DEFAULT_ETAGS) ? /(.*?)(%%?>|\z)/m : /(.*?)(#{etags.join('|')}|\z)/m
scanner = StringScanner.new(@src)
while ! scanner.eos?
scanner.scan(@stag ? etag_reg : stag_reg)