httpx/profiler/helpers.rb
HoneyryderChuck f56619efba fix: support webmock retries / response sequences
The previous implementation of the webmock plugin bypassed the
connection layer, which made it ignore key plugins like the retries
plugin. The whole plugin was redone so that it'd hook at the connection
level when piping requests.

A small difficulty was on how to handle the connection initialization
state when needing to unmock, as name resolving triggers before requests
are piped. A hack with a #once callback was implemented.

Fixes #170
2021-12-26 23:52:10 +02:00

99 lines
2.3 KiB
Ruby

# frozen_string_literal: true
require "objspace"
unless ObjectSpace.method_defined?(:memsize_of_all)
module ObjectSpace
module_function
def memsize_of_all(klass = false)
total = 0
total_mem = 0
ObjectSpace.each_object(klass) do |e|
total += 1
total_mem += ObjectSpace.memsize_of(e)
end
[total, total_mem]
end
end
end
module ProfilerHelpers
module_function
def measure_time
initial = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
yield
ensure
total = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) - initial
puts "Took #{total} milliseconds to run!"
end
def measure_rss
rss_proc = lambda do
ps_call = `ps -p #{Process.pid} -o rss -h`
/\d+/.match(ps_call)[0].to_i
end
prev_rss = rss_proc.call
yield
ensure
next_rss = rss_proc.call
puts "Increase: rss -> #{next_rss - prev_rss} kylobytes"
end
def measure_mem_size
httpx_classes = [
HTTPX,
HTTPX::Connection,
HTTPX::Parser,
HTTPX::Resolver,
].map { |klass| [klass, klass.constants.map { |cons| klass.const_get(cons) }] }
.flatten
.grep(Class)
http2_next_classes = HTTP2Next.constants.map { |sym| HTTP2Next.const_get(sym) }.grep(Class)
obj_memsize_proc = lambda do
[*httpx_classes, *http2_next_classes, Hash, Array, String].to_h do |klass|
count, size = ObjectSpace.memsize_of_all(klass)
[klass, [count, size]]
end
end
prev_memsize = obj_memsize_proc.call
GC.start
yield
ensure
GC.start
next_memsize = obj_memsize_proc.call
next_memsize.each do |klass, (count, size)|
prev_count, prev_size = prev_memsize[klass]
current_count = count - prev_count
next if current_count.zero?
current_size = size - prev_size
puts "#{klass} -> objects: (#{current_count}), size: (#{current_size})"
end
end
def measure_gc_stat
prev_stat = GC.stat
yield
ensure
next_stat = GC.stat
next_stat.each do |k, v|
puts "#{k}: #{prev_stat[k]} -> #{v}"
end
end
def memory_profile(&block)
require "memory_profiler"
MemoryProfiler.report(allow_files: ["lib/httpx"], &block).pretty_print
end
end