diff options
author | Jeremy Evans <code@jeremyevans.net> | 2018-05-18 15:08:38 -0700 |
---|---|---|
committer | Jeremy Evans <code@jeremyevans.net> | 2018-05-18 15:08:38 -0700 |
commit | 8b10a9414dd30817b1fc9c4c8cb7600cca0d15b3 (patch) | |
tree | 72b0b3054a26919407c3aa435ed4a3e666d8d5cc /actionpack | |
parent | 1efbc634b5707cfca1bec0cf39f90520396a979b (diff) | |
download | rails-8b10a9414dd30817b1fc9c4c8cb7600cca0d15b3.tar.gz rails-8b10a9414dd30817b1fc9c4c8cb7600cca0d15b3.tar.bz2 rails-8b10a9414dd30817b1fc9c4c8cb7600cca0d15b3.zip |
Speed up xor_byte_strings by 70%
Benchmark:
```ruby
require 'benchmark'
require 'benchmark/ips'
require 'securerandom'
def xor_byte_strings(s1, s2) # :doc:
s2_bytes = s2.bytes
s1.each_byte.with_index { |c1, i| s2_bytes[i] ^= c1 }
s2_bytes.pack("C*")
end
def xor_byte_strings_new(s1, s2) # :doc:
s2 = s2.dup
size = s1.bytesize
i = 0
while i < size
s2.setbyte(i, s1.getbyte(i) ^ s2.getbyte(i))
i += 1
end
s2
end
s1 = SecureRandom.random_bytes(32)
s2 = SecureRandom.random_bytes(32)
Benchmark.ips do |x|
x.report("current"){xor_byte_strings(s1, s2)}
x.report("new"){xor_byte_strings_new(s1, s2)}
x.compare!
end
100000.times do |i|
s3 = SecureRandom.random_bytes(32)
s4 = SecureRandom.random_bytes(32)
raise unless xor_byte_strings(s3, s4) == xor_byte_strings_new(s3, s4)
end
```
Results on ruby 2.5.1:
```
Warming up --------------------------------------
current 6.519k i/100ms
new 10.508k i/100ms
Calculating -------------------------------------
current 84.723k (_ 0.4%) i/s - 423.735k in 5.001456s
new 145.871k (_ 0.3%) i/s - 735.560k in 5.042606s
Comparison:
new: 145870.6 i/s
current: 84723.4 i/s - 1.72x slower
```
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/lib/action_controller/metal/request_forgery_protection.rb | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index fc9cf8aaff..953f3c47ed 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -400,9 +400,14 @@ module ActionController #:nodoc: end def xor_byte_strings(s1, s2) # :doc: - s2_bytes = s2.bytes - s1.each_byte.with_index { |c1, i| s2_bytes[i] ^= c1 } - s2_bytes.pack("C*") + s2 = s2.dup + size = s1.bytesize + i = 0 + while i < size + s2.setbyte(i, s1.getbyte(i) ^ s2.getbyte(i)) + i += 1 + end + s2 end # The form's authenticity parameter. Override to provide your own. |