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