Project

General

Profile

Feature #22463 » ruby_level.rb

watson1978 (Shizuo Fujita), 10/22/2026 04:24 AM

 
require 'benchmark'
require 'tmpdir'

line = ("a" * 1023 + "\n").b
s = line * 65_536 # 64 MB of 1 KB lines
short = ("a" * 15 + "\n").b * 4_194_304 # 64 MB of 16 B lines

def best(n = 3) = Array.new(n) { Benchmark.realtime { yield } }.min
gbps = ->(bytes, t) { format('%.2f GB/s', bytes / t / 1e9) }

r = {}
r['String#index("\n")'] = gbps.(s.bytesize, best { pos = -1; while (pos = s.index("\n", pos + 1)); end })
r['String#index, 16 B lines'] = gbps.(short.bytesize, best { pos = -1; while (pos = short.index("\n", pos + 1)); end })
r['String#index, no match'] = gbps.(s.bytesize, best { raise if s.index("z") })
r['String#index(/\n/)'] = gbps.(s.bytesize, best { pos = -1; while (pos = s.index(/\n/, pos + 1)); end })
r['String#each_line'] = gbps.(s.bytesize, best { s.each_line { } })
Dir.mktmpdir('memchr-bench') do |dir|
path = File.join(dir, 'lines.bin')
File.binwrite(path, line * 262_144) # 256 MB
File.open(path, 'rb') { |f| f.read } # warm the page cache
r['IO#read (1 MB chunks)'] = gbps.(256 << 20, best { File.open(path, 'rb') { |f| buf = String.new; while f.read(1 << 20, buf); end } })
r['IO#each_line'] = gbps.(256 << 20, best { File.open(path, 'rb') { |f| f.each_line { } } })
end
puts RUBY_DESCRIPTION
puts "string encoding: #{s.encoding}, file mode: rb, best of 3"
r.each { |k, v| puts format('%-24s %s', k, v) }
(4-4/5)