Skip to content

Instantly share code, notes, and snippets.

@t3hk0d3
Last active March 9, 2017 18:20
Show Gist options
  • Save t3hk0d3/6812c11b8b8180fb3780be29332498cd to your computer and use it in GitHub Desktop.
Save t3hk0d3/6812c11b8b8180fb3780be29332498cd to your computer and use it in GitHub Desktop.
Warming up --------------------------------------
functional_xor 16.702k i/100ms
iterator_xor 17.805k i/100ms
pack_xor 18.711k i/100ms
.each_byte 3.232k i/100ms
.bytes 16.976k i/100ms
.getbyte 23.730k i/100ms
.byteslice 17.928k i/100ms
.getbyte 8 28.353k i/100ms
.byteslice 8 19.803k i/100ms
.getbyte + pack 32.979k i/100ms
xor5 49.542k i/100ms
xor6 18.426k i/100ms
8byte hack 48.279k i/100ms
Calculating -------------------------------------
functional_xor 193.317k (± 8.0%) i/s - 968.716k
iterator_xor 208.020k (± 5.6%) i/s - 1.050M
pack_xor 225.964k (± 8.5%) i/s - 1.123M
.each_byte 36.867k (± 6.0%) i/s - 184.224k
.bytes 215.284k (± 3.9%) i/s - 1.086M
.getbyte 333.548k (± 4.5%) i/s - 1.685M
.byteslice 221.040k (± 4.9%) i/s - 1.112M
.getbyte 8 334.545k (± 4.8%) i/s - 1.673M
.byteslice 8 221.638k (± 4.7%) i/s - 1.109M
.getbyte + pack 400.701k (± 5.1%) i/s - 2.012M
xor5 714.254k (± 5.5%) i/s - 3.567M
xor6 235.222k (± 4.5%) i/s - 1.179M
8byte hack 842.431k (± 4.7%) i/s - 4.249M
Comparison:
8byte hack: 842430.8 i/s
xor5: 714253.6 i/s - 1.18x slower
.getbyte + pack: 400701.3 i/s - 2.10x slower
.getbyte 8: 334545.4 i/s - 2.52x slower
.getbyte: 333547.6 i/s - 2.53x slower
xor6: 235221.8 i/s - 3.58x slower
pack_xor: 225963.6 i/s - 3.73x slower
.byteslice 8: 221637.5 i/s - 3.80x slower
.byteslice: 221039.5 i/s - 3.81x slower
.bytes: 215284.4 i/s - 3.91x slower
iterator_xor: 208020.0 i/s - 4.05x slower
functional_xor: 193316.5 i/s - 4.36x slower
.each_byte: 36866.7 i/s - 22.85x slower
require 'benchmark/ips'
STR1 = 'qwertyui'.freeze
STR2 = 'zxcvbnm,'.freeze
def functional_xor(str1, str2)
str1.bytes.zip(str2.bytes).map { |byte1, byte2| (byte1 ^ byte2).chr }.join
end
def iterator_xor(str1, str2)
result = "\x00" * str1.size
str1_bytes = str1.bytes
str2_bytes = str2.bytes
str1_bytes.each_with_index do |byte, index|
result[index] = (byte ^ str2_bytes[index]).chr
end
result
end
def pack_xor(str1, str2)
str1.bytes.zip(str2.bytes).map { |byte1, byte2| byte1 ^ byte2 }.pack('C*')
end
Benchmark.ips do |x|
# Configure the number of seconds used during
# the warmup phase (default 2) and calculation phase (default 5)
x.report('functional_xor') do
functional_xor(STR1, STR2)
end
x.report('iterator_xor') do
iterator_xor(STR1, STR2)
end
x.report('pack_xor') do
pack_xor(STR1, STR2)
end
x.report('.each_byte') { STR1.each_byte.zip(STR2.each_byte).map { |byte1, byte2| (byte1 ^ byte2).chr }.join }
x.report('.bytes') { STR1.bytes.zip(STR2.bytes).map { |b1, b2| (b1 ^ b2).chr }.join }
x.report('.getbyte') { Array.new(STR1.bytesize) { |i| (STR1.getbyte(i) ^ STR2.getbyte(i)).chr }.join }
x.report('.byteslice') { Array.new(STR1.bytesize) { |i| (STR1.byteslice(i).ord ^ STR2.byteslice(i).ord).chr }.join }
x.report('.getbyte 8') { Array.new(8) { |i| (STR1.getbyte(i) ^ STR2.getbyte(i)).chr }.join }
x.report('.byteslice 8') { Array.new(8) { |i| (STR1.byteslice(i).ord ^ STR2.byteslice(i).ord).chr }.join }
x.report('.getbyte + pack') { Array.new(STR1.bytesize) { |i| STR1.getbyte(i) ^ STR2.getbyte(i) }.pack('C*') }
x.report('xor5') do
s = []
STR1.unpack('Q*').zip(STR2.unpack('Q*')) {|a,b| s.push( (a||0) ^ (b||0) ) }
s.pack('Q*')
end
x.report('xor6') do
s = []
STR1.unpack('C*').zip(STR2.unpack('C*')) {|a,b| s.push( (a||0) ^ (b||0) ) }
s.pack('C*')
end
x.report('8byte hack') do
[STR1.unpack('Q').first ^ STR2.unpack('Q').first].pack('Q')
end
x.compare!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment