|
#!/usr/bin/env ruby
|
|
# Memory impact of retaining many String#byteslice results, for
|
|
# https://bugs.ruby-lang.org/issues/22186.
|
|
#
|
|
# Usage: ruby misc/str_subseq_memory.rb [SIZE...]
|
|
|
|
require "objspace"
|
|
|
|
SIZES = ARGV.empty? ? [10, 50, 100, 250, 500, 999, 1000] : ARGV.map { |a| Integer(a) }
|
|
N = 200_000
|
|
|
|
SRC = ("0123456789abcdef" * 128).freeze
|
|
|
|
def rss_kb
|
|
`ps -o rss= -p #{Process.pid}`.to_i
|
|
end
|
|
|
|
puts RUBY_DESCRIPTION
|
|
printf("%6s %11s %11s %13s %s\n", "size", "per-slice", "total", "RSS delta", "flags")
|
|
|
|
SIZES.each do |size|
|
|
beg = SRC.bytesize - size
|
|
r, w = IO.pipe
|
|
fork do
|
|
r.close
|
|
GC.start
|
|
before_mem = ObjectSpace.memsize_of_all(String)
|
|
before_rss = rss_kb
|
|
slices = Array.new(N) { SRC.byteslice(beg, size) }
|
|
GC.start
|
|
total = ObjectSpace.memsize_of_all(String) - before_mem
|
|
rss = rss_kb - before_rss
|
|
dump = ObjectSpace.dump(slices.first)
|
|
flags = %w[embedded shared].select { |f| dump.include?("\"#{f}\":true") }.join(",")
|
|
w.puts [ObjectSpace.memsize_of(slices.first), total, rss, flags].join(" ")
|
|
slices.clear
|
|
end
|
|
w.close
|
|
per, total, rss, flags = r.read.split
|
|
Process.wait
|
|
printf("%6d %10dB %9.1fMB %11.1fMB %s\n",
|
|
size, per, total.to_i / 1024.0 / 1024, rss.to_i / 1024.0, flags || "(heap copy)")
|
|
end
|