Skip to content

Instantly share code, notes, and snippets.

@ganmacs
Created July 26, 2019 10:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ganmacs/3f517c79881f56547cde305ae7a86b35 to your computer and use it in GitHub Desktop.
Save ganmacs/3f517c79881f56547cde305ae7a86b35 to your computer and use it in GitHub Desktop.
slice+freeze vs slice!
class FIFO
def initialize(from_encoding, encoding)
@from_encoding = from_encoding
@encoding = encoding
@need_enc = from_encoding != encoding
@buffer = ''.force_encoding(from_encoding)
@eol = "\n".encode(from_encoding).freeze
end
attr_reader :from_encoding, :encoding, :buffer
def <<(chunk)
orig_encoding = chunk.encoding
chunk.force_encoding(from_encoding)
@buffer << chunk
# Thus the encoding needs to be reverted back here
chunk.force_encoding(orig_encoding)
end
def convert(s)
if @need_enc
s.encode!(@encoding, @from_encoding)
else
s
end
rescue
s.encode!(@encoding, @from_encoding, :invalid => :replace, :undef => :replace)
end
def next_line
idx = @buffer.index(@eol)
convert(@buffer.slice!(0, idx + 1)) unless idx.nil?
end
def next_line2
idx = @buffer.index(@eol)
unless idx.nil?
@buffer.freeze
rbuf = @buffer.slice(0, idx + 1)
@buffer = @buffer.slice(idx + 1, @buffer.size)
convert(rbuf)
end
end
def bytesize
@buffer.bytesize
end
end
require 'benchmark'
log = "this is a line of log\n"
f1 = FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
f2 = FIFO.new(Encoding::ASCII_8BIT, Encoding::ASCII_8BIT)
N = 40000
N.times do
f1 << log
f2 << log
end
puts "Ruby version: #{RUBY_VERSION}"
Benchmark.bmbm do |x|
x.report('slice!') do
(N/2).times do
if f1.next_line.nil?
raise
end
end
end
x.report('slice') do
(N/2).times do
if f2.next_line2.nil?
raise
end
end
end
end

ruby 2.1.10

$ ruby app.rb
Ruby version: 2.1.10
Rehearsal ------------------------------------------
slice!   2.210000   2.390000   4.600000 (  4.614415)
slice    0.010000   0.000000   0.010000 (  0.008950)
--------------------------------- total: 4.610000sec

             user     system      total        real
slice!   0.920000   1.060000   1.980000 (  1.990008)
slice    0.010000   0.000000   0.010000 (  0.007840)

ruby 2.4.6

$ ruby app.rb
Ruby version: 2.4.6
Rehearsal ------------------------------------------
slice!   2.240000   2.450000   4.690000 (  4.715899)
slice    0.010000   0.000000   0.010000 (  0.009899)
--------------------------------- total: 4.700000sec

             user     system      total        real
slice!   0.870000   1.090000   1.960000 (  1.957490)
slice    0.010000   0.000000   0.010000 (  0.013238)

ruby 2.6.3

$ ruby app.rb
Ruby version: 2.6.3
Rehearsal ------------------------------------------
slice!   2.221282   2.468471   4.689753 (  4.701863)
slice    0.009605   0.001857   0.011462 (  0.011467)
--------------------------------- total: 4.701215sec

             user     system      total        real
slice!   0.867567   1.087543   1.955110 (  1.958745)
slice    0.007350   0.000164   0.007514 (  0.007529)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment