Skip to content

Commit

Permalink
speed up string xor operation and reduce object allocations
Browse files Browse the repository at this point in the history
```
[aaron@TC rails (master)]$ cat xor.rb
a = "\x14b\"\xB4P8\x05\x8D\xC74\xC3\xEC}\xFDf\x8E!h\xCF^\xBF\xA5%\xC6\xF0\xA9\xF9x\x04\xFA\xF1\x82"
b = "O.\xF7\x01\xA9D\xA3\xE1D\x7FU\x85\xFC\x8Ak\e\x04\x8A\x97\x91\xD01\x02\xA4G\x1EIf:Y\x0F@"

def xor_byte_strings(s1, s2)
  s1.bytes.zip(s2.bytes).map { |(c1,c2)| c1 ^ c2 }.pack('c*')
end

def xor_byte_strings2(s1, s2)
  s2_bytes = s2.bytes
  s1.bytes.map.with_index { |c1, i| c1 ^ s2_bytes[i] }.pack('c*')
end

require 'benchmark/ips'
require 'allocation_tracer'

Benchmark.ips do |x|
  x.report 'xor_byte_strings' do
    xor_byte_strings a, b
  end

  x.report 'xor_byte_strings2' do
    xor_byte_strings2 a, b
  end
end

ObjectSpace::AllocationTracer.setup(%i{type})
result = ObjectSpace::AllocationTracer.trace do
  xor_byte_strings a, b
end
p :xor_byte_strings => result
ObjectSpace::AllocationTracer.clear
result = ObjectSpace::AllocationTracer.trace do
  xor_byte_strings2 a, b
end
p :xor_byte_strings2 => result
[aaron@TC rails (master)]$ ruby -I~/git/allocation_tracer/lib xor.rb
Calculating -------------------------------------
    xor_byte_strings    10.087k i/100ms
   xor_byte_strings2    11.339k i/100ms
-------------------------------------------------
    xor_byte_strings    108.386k (± 5.8%) i/s -    544.698k
   xor_byte_strings2    122.239k (± 3.0%) i/s -    612.306k
{:xor_byte_strings=>{[:T_ARRAY]=>[38, 0, 0, 0, 0, 0], [:T_STRING]=>[2, 0, 0, 0, 0, 0]}}
{:xor_byte_strings2=>{[:T_ARRAY]=>[3, 0, 0, 0, 0, 0], [:T_DATA]=>[1, 0, 0, 0, 0, 0], [:T_IMEMO]=>[2, 0, 0, 0, 0, 0], [:T_STRING]=>[2, 0, 0, 0, 0, 0]}}
```
  • Loading branch information
tenderlove committed Feb 8, 2016
1 parent e6fc78b commit 02c3867
Showing 1 changed file with 2 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,8 @@ def per_form_csrf_token(session, action_path, method)
end

def xor_byte_strings(s1, s2)
s1.bytes.zip(s2.bytes).map { |(c1,c2)| c1 ^ c2 }.pack('c*')
s2_bytes = s2.bytes
s1.bytes.map.with_index { |c1, i| c1 ^ s2_bytes[i] }.pack('c*')
end

# The form's authenticity parameter. Override to provide your own.
Expand Down

0 comments on commit 02c3867

Please sign in to comment.