aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2018-05-18 15:08:38 -0700
committerJeremy Evans <code@jeremyevans.net>2018-05-18 15:08:38 -0700
commit8b10a9414dd30817b1fc9c4c8cb7600cca0d15b3 (patch)
tree72b0b3054a26919407c3aa435ed4a3e666d8d5cc /actionpack
parent1efbc634b5707cfca1bec0cf39f90520396a979b (diff)
downloadrails-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.rb11
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.