Created
April 22, 2021 15:32
-
-
Save casperisfine/f6d2728ba91721929e775bc14af7438f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# frozen_string_literal: true | |
require 'benchmark/ips' | |
require 'active_support/all' | |
require 'zlib' | |
sizes = if ENV['SIZES'] | |
ENV['SIZES'].split(',').map(&:to_i) | |
else | |
[0, 10, 2_000] | |
end | |
module ActiveSupport | |
module Cache | |
module Coders | |
module OptimizedCoder | |
extend self | |
COMPRESSED = 0x01 | |
SERIALIZED = 0x02 | |
def dump(entry) | |
dump_compressed(entry, false) | |
end | |
def dump_compressed(entry, threshold) | |
flags = 0 | |
header = [entry.expires_at, entry.version] | |
header.pop until header.empty? || !header.last.nil? | |
header_payload = Marshal.dump(header) | |
value = entry.value | |
if value.is_a?(String) | |
value_payload = entry.value | |
else | |
flags |= SERIALIZED | |
value_payload = Marshal.dump(value) | |
end | |
if threshold && value_payload.bytesize >= threshold | |
compressed_payload = Zlib::Deflate.deflate(value_payload) | |
if compressed_payload.bytesize < value_payload.bytesize | |
value_payload = compressed_payload | |
flags |= COMPRESSED | |
end | |
end | |
flags.chr << header_payload.bytesize.chr << header_payload << value_payload | |
end | |
def load(payload) | |
flags, header_size = payload.unpack('CC') | |
header = Marshal.load(payload.byteslice(2..-1)) | |
value_payload = payload.byteslice((2 + header_size)..-1) | |
if flags & COMPRESSED > 0 | |
if flags & SERIALIZED > 0 | |
Entry.new(value_payload, compressed: true, expires_at: header[0], version: header[1]) | |
else | |
Entry.new(Zlib::Inflate.inflate(value_payload), expires_at: header[0], version: header[1]) | |
end | |
elsif flags & SERIALIZED > 0 | |
Entry.new(Marshal.load(value_payload), expires_at: header[0], version: header[1]) | |
else | |
Entry.new(value_payload, expires_at: header[0], version: header[1]) | |
end | |
end | |
end | |
end | |
end | |
end | |
sizes.each do |bytesize| | |
puts "================ #{bytesize} bytes ================" | |
if bytesize == 0 | |
entry_marshal = Marshal.dump(ActiveSupport::Cache::Entry.new('')) | |
entry_pack = ActiveSupport::Cache::Coders::Rails70Coder.dump(ActiveSupport::Cache::Entry.new('', compress: false)) | |
opt_entry_pack = ActiveSupport::Cache::Coders::OptimizedCoder.dump(ActiveSupport::Cache::Entry.new('', compress: false)) | |
else | |
string = ('A'..'z').cycle.take(bytesize).join | |
entry_marshal = Marshal.dump(ActiveSupport::Cache::Entry.new(string, expires_in: 1.hour, version: "v42").compressed(1_024)) | |
entry_pack = ActiveSupport::Cache::Coders::Rails70Coder.dump_compressed(ActiveSupport::Cache::Entry.new(string, expires_in: 1.hour, version: "v42", compress: false), 1_024) | |
opt_entry_pack = ActiveSupport::Cache::Coders::OptimizedCoder.dump_compressed(ActiveSupport::Cache::Entry.new(string, expires_in: 1.hour, version: "v42", compress: false), 1_024) | |
end | |
puts "Marshal.dump.bytesize: #{entry_marshal.bytesize}" | |
puts "EntryCoder.dump.bytesize: #{entry_pack.bytesize}" | |
puts "OptimizedCoder.dump.bytesize: #{entry_pack.bytesize}" | |
puts | |
Benchmark.ips do |x| | |
x.report('Marshal.dump') { Marshal.dump(ActiveSupport::Cache::Entry.new(string, expires_in: 1.hour, version: "v42").compressed(1_024)) } | |
x.report('Rails70.dump') { ActiveSupport::Cache::Coders::Rails70Coder.dump_compressed(ActiveSupport::Cache::Entry.new(string, expires_in: 1.hour, version: "v42", compress: false), 1_024) } | |
x.report('Optimized.dump') { ActiveSupport::Cache::Coders::OptimizedCoder.dump_compressed(ActiveSupport::Cache::Entry.new(string, expires_in: 1.hour, version: "v42", compress: false), 1_024) } | |
x.compare! | |
end | |
puts | |
Benchmark.ips do |x| | |
x.report('Marshal.load') { Marshal.load(entry_marshal).value } | |
x.report('Rails70.load') { ActiveSupport::Cache::Coders::Rails70Coder.load(entry_pack).value } | |
x.report('OptimizedCoder.load') { ActiveSupport::Cache::Coders::OptimizedCoder.load(opt_entry_pack).value } | |
x.compare! | |
end | |
puts | |
puts | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
================ 0 bytes ================ | |
Marshal.dump.bytesize: 90 | |
EntryCoder.dump.bytesize: 13 | |
OptimizedCoder.dump.bytesize: 13 | |
Warming up -------------------------------------- | |
Marshal.dump 17.129k i/100ms | |
Rails70.dump 21.300k i/100ms | |
Optimized.dump 16.390k i/100ms | |
Calculating ------------------------------------- | |
Marshal.dump 170.537k (± 1.4%) i/s - 856.450k in 5.023018s | |
Rails70.dump 215.330k (± 1.3%) i/s - 1.086M in 5.045690s | |
Optimized.dump 163.612k (± 1.4%) i/s - 819.500k in 5.009718s | |
Comparison: | |
Rails70.dump: 215329.6 i/s | |
Marshal.dump: 170537.1 i/s - 1.26x (± 0.00) slower | |
Optimized.dump: 163612.0 i/s - 1.32x (± 0.00) slower | |
Warming up -------------------------------------- | |
Marshal.load 36.668k i/100ms | |
Rails70.load 55.709k i/100ms | |
OptimizedCoder.load 51.832k i/100ms | |
Calculating ------------------------------------- | |
Marshal.load 366.149k (± 1.4%) i/s - 1.833M in 5.008249s | |
Rails70.load 550.303k (± 1.5%) i/s - 2.785M in 5.062743s | |
OptimizedCoder.load 517.866k (± 2.0%) i/s - 2.592M in 5.006465s | |
Comparison: | |
Rails70.load: 550303.1 i/s | |
OptimizedCoder.load: 517866.1 i/s - 1.06x (± 0.00) slower | |
Marshal.load: 366148.8 i/s - 1.50x (± 0.00) slower | |
================ 10 bytes ================ | |
Marshal.dump.bytesize: 127 | |
EntryCoder.dump.bytesize: 53 | |
OptimizedCoder.dump.bytesize: 53 | |
Warming up -------------------------------------- | |
Marshal.dump 14.675k i/100ms | |
Rails70.dump 20.229k i/100ms | |
Optimized.dump 19.653k i/100ms | |
Calculating ------------------------------------- | |
Marshal.dump 146.104k (± 0.9%) i/s - 733.750k in 5.022520s | |
Rails70.dump 203.623k (± 1.1%) i/s - 1.032M in 5.067272s | |
Optimized.dump 198.870k (± 1.2%) i/s - 1.002M in 5.040741s | |
Comparison: | |
Rails70.dump: 203623.3 i/s | |
Optimized.dump: 198870.5 i/s - same-ish: difference falls within error | |
Marshal.dump: 146104.4 i/s - 1.39x (± 0.00) slower | |
Warming up -------------------------------------- | |
Marshal.load 29.581k i/100ms | |
Rails70.load 43.199k i/100ms | |
OptimizedCoder.load 40.047k i/100ms | |
Calculating ------------------------------------- | |
Marshal.load 296.891k (± 1.1%) i/s - 1.509M in 5.082104s | |
Rails70.load 431.656k (± 1.2%) i/s - 2.160M in 5.004583s | |
OptimizedCoder.load 404.179k (± 5.1%) i/s - 2.042M in 5.072898s | |
Comparison: | |
Rails70.load: 431656.3 i/s | |
OptimizedCoder.load: 404178.5 i/s - 1.07x (± 0.00) slower | |
Marshal.load: 296890.8 i/s - 1.45x (± 0.00) slower | |
================ 2000 bytes ================ | |
Marshal.dump.bytesize: 221 | |
EntryCoder.dump.bytesize: 127 | |
OptimizedCoder.dump.bytesize: 127 | |
Warming up -------------------------------------- | |
Marshal.dump 3.953k i/100ms | |
Rails70.dump 4.023k i/100ms | |
Optimized.dump 4.778k i/100ms | |
Calculating ------------------------------------- | |
Marshal.dump 39.823k (± 1.1%) i/s - 201.603k in 5.063150s | |
Rails70.dump 40.129k (± 1.0%) i/s - 201.150k in 5.013145s | |
Optimized.dump 47.953k (± 1.2%) i/s - 243.678k in 5.082282s | |
Comparison: | |
Optimized.dump: 47953.3 i/s | |
Rails70.dump: 40128.8 i/s - 1.19x (± 0.00) slower | |
Marshal.dump: 39822.7 i/s - 1.20x (± 0.00) slower | |
Warming up -------------------------------------- | |
Marshal.load 10.688k i/100ms | |
Rails70.load 13.666k i/100ms | |
OptimizedCoder.load 12.594k i/100ms | |
Calculating ------------------------------------- | |
Marshal.load 107.654k (± 1.3%) i/s - 545.088k in 5.064150s | |
Rails70.load 133.274k (± 2.6%) i/s - 669.634k in 5.028035s | |
OptimizedCoder.load 124.683k (± 1.7%) i/s - 629.700k in 5.051781s | |
Comparison: | |
Rails70.load: 133273.6 i/s | |
OptimizedCoder.load: 124683.4 i/s - 1.07x (± 0.00) slower | |
Marshal.load: 107654.1 i/s - 1.24x (± 0.00) slower | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment