rails/rails — pull request #13495 by norman (2013-12-26 15:49:31+00:00)
Title: Use String#scrub when available to tidy bytes

Continuing on the fine work by @burke in rails/rails#10355 this makes `tidy_bytes` use `String#scrub` on Ruby 2.1 and up. This yields another performance bump running the following benchmark - adapted from @burke's original to ensure we're measuring the performance when bytes are actually being changed:

```ruby
require 'benchmark'
require 'active_support/multibyte'

single_byte_cases = {
"\x21" => "!", # Valid ASCII byte, low
"\x41" => "A", # Valid ASCII byte, mid
"\x7E" => "~", # Valid ASCII byte, high
"\x80" => "€", # Continuation byte, low (cp125)
"\x94" => "”", # Continuation byte, mid (cp125)
"\x9F" => "Ÿ", # Continuation byte, high (cp125)
"\xC0" => "À", # Overlong encoding, start of 2-byte sequence, but codepoint < 128
"\xC1" => "Á", # Overlong encoding, start of 2-byte sequence, but codepoint < 128
"\xC2" => "Â", # Start of 2-byte sequence, low
"\xC8" => "È", # Start of 2-byte sequence, mid
"\xDF" => "ß", # Start of 2-byte sequence, high
"\xE0" => "à", # Start of 3-byte sequence, low
"\xE8" => "è", # Start of 3-byte sequence, mid
"\xEF" => "ï", # Start of 3-byte sequence, high
"\xF0" => "ð", # Start of 4-byte sequence
"\xF1" => "ñ", # Unused byte
"\xFF" => "ÿ", # Restricted byte
"\x00" => "\x00" # null char
}

str = single_byte_cases.keys.join

u = ActiveSupport::Multibyte::Unicode

res = Benchmark.realtime do
10_000.times do
u.tidy_bytes(str)
end
end

puts "tidy_bytes took #{res / 10}ms"
```

On: ruby 2.1.0p0 (2013-12-25 revision 44422) [x86_64-darwin13.0]

Without change: tidy_bytes took 0.2071831ms
With change: tidy_bytes took 0.11698470000000001ms