Checking this: https://github.com/rails/rails/commit/63cd9432265a32d222353b535d60333c2a6a5125
test.rb:
def h_via_encode(s)
s = s.to_s
if s.html_safe?
s
else
s.encode(s.encoding, :xml => :attr)[1...-1].html_safe
end
end
HTML_ESCAPE = { '&' => '&', '>' => '>', '<' => '<', '"' => '"' }
def h_via_gsub(s)
s = s.to_s
if s.html_safe?
s
else
silence_warnings { s.gsub(/[&"><]/n) { |special| HTML_ESCAPE[special] }.html_safe }
end
end
def time_and_space(iter = 10000, &block)
ObjectSpace.garbage_collect
s=GC.malloc_allocated_size if GC.respond_to?(:malloc_allocated_size)
c=GC.count
t = Benchmark.realtime do
iter.to_i.times do
yield
end
end
m = (GC.malloc_allocated_size - s).to_f/(1024.0*1024.0) if GC.respond_to?(:malloc_allocated_size)
m ||= -1.0
g = GC.count - c
"#{ '%.3f' % t} sec #{'%.3f' % m} MB #{g} collections #{iter} iterations"
end
base_with_specials = '<script>alert("foo & bar & baz");</script>'
base_without_specials = 'Laborum next level organic nihil cardigan.'
test_strings = {
'with_special_1' => base_with_specials,
'no_special_1' => base_without_specials,
'with_special_10' => base_with_specials * 10,
'no_special_10' => base_without_specials * 10,
'with_special_100' => base_with_specials * 100,
'no_special_100' => base_without_specials * 100
} ; nil
test_strings.each_pair do |name, string|
puts "\n#{name} length: #{string.length}"
[100, 1000, 10000].each do |iter|
puts "via_encode: " << time_and_space(iter) { h_via_encode(string) }
puts "via_gsub: " << time_and_space(iter) { h_via_gsub(string) }
end
end ; nil
Context: osx lion, MBP:
$ rvm install ruby-1.9.3-p125 -n basic
$ rvm install ruby-1.9.3-p125 -n gcdata --patch gcdata
~/projects/rails $ git checkout 3-1-stable
$ rvm use ruby-1.9.3-p125-basic@rails --create
$ bundle install
$ echo "load '../test.rb'" | tools/console
Switch to inspect mode.
load '../test.rb'
with_special_1 length: 42
via_encode: 0.001 sec -1.000 MB 0 collections 100 iterations
via_gsub: 0.001 sec -1.000 MB 0 collections 100 iterations
via_encode: 0.021 sec -1.000 MB 1 collections 1000 iterations
via_gsub: 0.010 sec -1.000 MB 0 collections 1000 iterations
via_encode: 0.211 sec -1.000 MB 11 collections 10000 iterations
via_gsub: 0.106 sec -1.000 MB 0 collections 10000 iterations
no_special_1 length: 42
via_encode: 0.001 sec -1.000 MB 0 collections 100 iterations
via_gsub: 0.000 sec -1.000 MB 0 collections 100 iterations
via_encode: 0.019 sec -1.000 MB 1 collections 1000 iterations
via_gsub: 0.003 sec -1.000 MB 0 collections 1000 iterations
via_encode: 0.195 sec -1.000 MB 11 collections 10000 iterations
via_gsub: 0.029 sec -1.000 MB 0 collections 10000 iterations
with_special_10 length: 420
via_encode: 0.007 sec -1.000 MB 0 collections 100 iterations
via_gsub: 0.005 sec -1.000 MB 0 collections 100 iterations
via_encode: 0.074 sec -1.000 MB 1 collections 1000 iterations
via_gsub: 0.054 sec -1.000 MB 0 collections 1000 iterations
via_encode: 0.756 sec -1.000 MB 13 collections 10000 iterations
via_gsub: 0.583 sec -1.000 MB 6 collections 10000 iterations
no_special_10 length: 420
via_encode: 0.006 sec -1.000 MB 0 collections 100 iterations
via_gsub: 0.000 sec -1.000 MB 0 collections 100 iterations
via_encode: 0.057 sec -1.000 MB 0 collections 1000 iterations
via_gsub: 0.003 sec -1.000 MB 0 collections 1000 iterations
via_encode: 0.576 sec -1.000 MB 1 collections 10000 iterations
via_gsub: 0.034 sec -1.000 MB 0 collections 10000 iterations
with_special_100 length: 4200
via_encode: 0.061 sec -1.000 MB 0 collections 100 iterations
via_gsub: 0.049 sec -1.000 MB 0 collections 100 iterations
via_encode: 0.597 sec -1.000 MB 0 collections 1000 iterations
via_gsub: 0.495 sec -1.000 MB 4 collections 1000 iterations
via_encode: 5.980 sec -1.000 MB 4 collections 10000 iterations
via_gsub: 5.021 sec -1.000 MB 41 collections 10000 iterations
no_special_100 length: 4200
via_encode: 0.053 sec -1.000 MB 0 collections 100 iterations
via_gsub: 0.001 sec -1.000 MB 0 collections 100 iterations
via_encode: 0.517 sec -1.000 MB 0 collections 1000 iterations
via_gsub: 0.008 sec -1.000 MB 0 collections 1000 iterations
via_encode: 5.039 sec -1.000 MB 2 collections 10000 iterations
via_gsub: 0.081 sec -1.000 MB 0 collections 10000 iterations
true
With gcdata:
~/projects/rails $ rvm use ruby-1.9.3-p125-gcdata@rails --create; bundle install; echo "load '../test.rb'" | tools/console
...
Seans-MacBook-Pro:~/projects/rails $ echo "load '../test.rb'" | tools/console
Switch to inspect mode.
load '../test.rb'
with_special_1 length: 42
via_encode: 0.001 sec 0.872 MB 0 collections 100 iterations
via_gsub: 0.001 sec 0.039 MB 0 collections 100 iterations
via_encode: 0.014 sec 8.722 MB 0 collections 1000 iterations
via_gsub: 0.011 sec 0.390 MB 0 collections 1000 iterations
via_encode: 0.151 sec 87.223 MB 1 collections 10000 iterations
via_gsub: 0.102 sec 3.901 MB 0 collections 10000 iterations
no_special_1 length: 42
via_encode: 0.001 sec 0.870 MB 0 collections 100 iterations
via_gsub: 0.000 sec 0.018 MB 0 collections 100 iterations
via_encode: 0.012 sec 8.694 MB 0 collections 1000 iterations
via_gsub: 0.003 sec 0.176 MB 0 collections 1000 iterations
via_encode: 0.133 sec 86.937 MB 1 collections 10000 iterations
via_gsub: 0.029 sec 1.755 MB 0 collections 10000 iterations
with_special_10 length: 420
via_encode: 0.007 sec 0.970 MB 0 collections 100 iterations
via_gsub: 0.006 sec 0.070 MB 0 collections 100 iterations
via_encode: 0.065 sec 9.701 MB 0 collections 1000 iterations
via_gsub: 0.055 sec 0.697 MB 0 collections 1000 iterations
via_encode: 0.659 sec 97.008 MB 1 collections 10000 iterations
via_gsub: 0.587 sec 6.972 MB 4 collections 10000 iterations
no_special_10 length: 420
via_encode: 0.006 sec 0.942 MB 0 collections 100 iterations
via_gsub: 0.000 sec 0.018 MB 0 collections 100 iterations
via_encode: 0.057 sec 9.415 MB 0 collections 1000 iterations
via_gsub: 0.003 sec 0.176 MB 0 collections 1000 iterations
via_encode: 0.571 sec 94.147 MB 1 collections 10000 iterations
via_gsub: 0.035 sec 1.755 MB 0 collections 10000 iterations
with_special_100 length: 4200
via_encode: 0.060 sec 1.949 MB 0 collections 100 iterations
via_gsub: 0.050 sec 0.430 MB 0 collections 100 iterations
via_encode: 0.587 sec 19.486 MB 0 collections 1000 iterations
via_gsub: 0.520 sec 4.302 MB 4 collections 1000 iterations
via_encode: 5.874 sec 194.855 MB 4 collections 10000 iterations
via_gsub: 5.172 sec 43.020 MB 41 collections 10000 iterations
no_special_100 length: 4200
via_encode: 0.050 sec 1.663 MB 0 collections 100 iterations
via_gsub: 0.001 sec 0.018 MB 0 collections 100 iterations
via_encode: 0.490 sec 16.625 MB 0 collections 1000 iterations
via_gsub: 0.008 sec 0.176 MB 0 collections 1000 iterations
via_encode: 4.982 sec 166.245 MB 2 collections 10000 iterations
via_gsub: 0.084 sec 1.755 MB 0 collections 10000 iterations
true