diff options
author | shik <shik.chen@gmail.com> | 2016-02-15 11:46:42 +0800 |
---|---|---|
committer | shik <shik.chen@gmail.com> | 2016-02-15 13:02:26 +0800 |
commit | e35e19a8b7edd355e76b7114be00dbc750453beb (patch) | |
tree | 141f39c9cfe247eee353488c66d3d31d4868528c /activerecord/lib/active_record/legacy_yaml_adapter.rb | |
parent | f432e129a7e70a96f4c0d55fa7152fc010e9ca5d (diff) | |
download | rails-e35e19a8b7edd355e76b7114be00dbc750453beb.tar.gz rails-e35e19a8b7edd355e76b7114be00dbc750453beb.tar.bz2 rails-e35e19a8b7edd355e76b7114be00dbc750453beb.zip |
Improve the performance of string xor operation
Use `each_byte` instead of `bytes` to speed up string xor operation and
reduce object allocations.
Inspired by commit 02c3867882d6d23b10df262a6db5f937ca69fb53.
``` ruby
require 'benchmark/ips'
require 'allocation_tracer'
a = 32.times.map { rand(256) }.pack('C*')
b = 32.times.map { rand(256) }.pack('C*')
def xor_byte_strings1(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
def xor_byte_strings3(s1, s2)
s2_bytes = s2.bytes
s1.each_byte.with_index { |c1, i| s2_bytes[i] ^= c1 }
s2_bytes.pack('C*')
end
fail if xor_byte_strings1(a, b) != xor_byte_strings2(a, b)
fail if xor_byte_strings1(a, b) != xor_byte_strings3(a, b)
Benchmark.ips do |x|
x.report('xor_byte_strings1') { xor_byte_strings1(a, b) }
x.report('xor_byte_strings2') { xor_byte_strings2(a, b) }
x.report('xor_byte_strings3') { xor_byte_strings3(a, b) }
x.compare!
end
Tracer = ObjectSpace::AllocationTracer
Tracer.setup(%i{type})
p xor_byte_strings1: Tracer.trace { xor_byte_strings1(a, b) }
p xor_byte_strings2: Tracer.trace { xor_byte_strings2(a, b) }
p xor_byte_strings3: Tracer.trace { xor_byte_strings3(a, b) }
```
```
Warming up --------------------------------------
xor_byte_strings1 10.668k i/100ms
xor_byte_strings2 11.814k i/100ms
xor_byte_strings3 13.139k i/100ms
Calculating -------------------------------------
xor_byte_strings1 116.667k (± 3.1%) i/s - 586.740k
xor_byte_strings2 129.932k (± 4.3%) i/s - 649.770k
xor_byte_strings3 142.506k (± 4.2%) i/s - 722.645k
Comparison:
xor_byte_strings3: 142506.3 i/s
xor_byte_strings2: 129932.4 i/s - 1.10x slower
xor_byte_strings1: 116666.8 i/s - 1.22x slower
{:xor_byte_strings1=>{[: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]}}
{:xor_byte_strings3=>{[:T_ARRAY]=>[1, 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]}}
```
Diffstat (limited to 'activerecord/lib/active_record/legacy_yaml_adapter.rb')
0 files changed, 0 insertions, 0 deletions