Skip to content

Instantly share code, notes, and snippets.

@arika arika/bm_read_lines.rb
Last active Oct 13, 2019

Embed
What would you like to do?
benchmark read lines and scan lines
# frozen_string_literal: true
require "benchmark"
require "strscan"
def open_file(filename = "development.log")
File.open(filename, "r") do |io|
yield io
end
end
def action(line)
# noop
end
Benchmark.bmbm do |bm|
bm.report("#read [all]") do
open_file do |io|
io.read
end
end
bm.report("#gets") do
open_file do |io|
while line = io.gets
action(line)
end
end
end
bm.report("#each_line") do
open_file do |io|
io.each_line do |line|
action(line)
end
end
end
[128, 512, 1024, 4096, 8192].each do |size|
bm.report("#sysread [#{size}]") do
open_file do |io|
buf = +""
rest = nil
while buf << io.sysread(size)
buf.each_line do |line|
unless line[-1] == "\n"
rest = line
break
end
action(line)
rest = nil
end
buf = rest || +""
end
rescue EOFError
action(rest) if rest
end
end
end
[128, 512, 1024, 4096, 8192].each do |size|
bm.report("#read [#{size}]") do
open_file do |io|
buf = +""
rest = nil
while buf << io.read(size)
buf.each_line do |line|
unless line[-1] == "\n"
rest = line
break
end
action(line)
rest = nil
end
if io.eof?
action(rest) if rest
break
end
buf = rest || +""
end
end
end
end
[128, 512, 1024, 4096, 8192].each do |size|
bm.report("#readpartial [#{size}]") do
open_file do |io|
buf = +""
rest = nil
while buf << io.readpartial(size)
buf.each_line do |line|
unless line[-1] == "\n"
rest = line
break
end
action(line)
rest = nil
end
if io.eof?
action(rest) if rest
break
end
buf = rest || +""
end
end
end
end
[128, 512, 1024, 4096, 8192].each do |size|
bm.report("StringScanner [#{size}]") do
s = StringScanner.new(+"")
open_file do |io|
while s << io.readpartial(size)
while line = s.scan_until(/\n/)
action(line)
end
if io.eof?
action(s.rest) if s.rest?
break
end
end
end
end
end
end
# frozen_string_literal: true
require "benchmark"
require "strscan"
def open_file(filename = "development.log")
File.open(filename, "r") do |io|
yield io
end
end
def time(year, month, day, hour, min, sec, usec)
Time.local(year.to_i, month.to_i, day.to_i, hour.to_i, min.to_i, sec.to_i, usec.to_i)
end
def action(*args)
$result << args if $result.size < 100
end
def setup
$result = []
end
def check
return if $expected == $result
raise unless $expected.size == $result.size
$expected.each_with_index do |expected, idx|
result = $result[idx]
unless expected == result
puts
p expected
p result
raise
end
end
end
pattern = "(.), \\[(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2}).(\\d+) #(\\d+)\\] \\S+ -- : "
setup
open_file do |io|
io.read.scan(/^#{pattern}(.*)\n/o) do |severity, *time_segs, pid, message|
time = time(*time_segs)
action(severity, time, pid.to_i, message.chomp)
end
end
$expected = $result
Benchmark.bmbm do |bm|
bm.report("#read [all]") do
setup
open_file do |io|
io.read.scan(/^#{pattern}(.*)\n/o) do |severity, *time_segs, pid, message|
time = time(*time_segs)
action(severity, time, pid.to_i, message.chomp)
end
end
check
end
bm.report("#gets") do
setup
open_file do |io|
while line = io.gets
next unless /\A#{pattern}/o =~ line
time = time($2, $3, $4, $5, $6, $7, $8)
action($1, time, $9.to_i, $'.chomp)
end
end
check
end
bm.report("#each_line") do
setup
open_file do |io|
io.each_line do |line|
next unless /\A#{pattern}/o =~ line
time = time($2, $3, $4, $5, $6, $7, $8)
action($1, time, $9.to_i, $'.chomp)
end
end
check
end
[4096, 8192, 1024 * 16, 1024 * 64, 1024 * 256].each do |size|
bm.report("#readpartial [#{size}]") do
setup
open_file do |io|
buf = +""
while buf << io.readpartial(size)
buf.scan(/^#{pattern}(.*)\n/o) do |severity, *time_segs, pid, message|
time = time(*time_segs)
action(severity, time, pid.to_i, message)
end
break if io.eof?
buf = $'.empty? ? +"" : $' if $'
end
end
check
end
end
[4096, 8192, 1024 * 16, 1024 * 64, 1024 * 256].each do |size|
bm.report("StringScanner [#{size}]") do
setup
s = StringScanner.new(+"")
open_file do |io|
while s << io.readpartial(size)
while line = s.skip_until(/^#{pattern}(.*)\n/o)
time = time(s[2], s[3], s[4], s[5], s[6], s[7], s[8])
action(s[1], time, s[9].to_i, s[10])
end
break if io.eof?
end
end
check
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.