class Benchmark::Malloc

Constants

VERSION

Attributes

generation[R]
warmup[R]

It runs Ruby VM before tracing object allocations

@api public

Public Class Methods

new(warmup: 0) click to toggle source

Create a memory allocation tracer

@api public

# File lib/benchmark/malloc.rb, line 31
def initialize(warmup: 0)
  @warmup = warmup
  @running = false
  @alloc_path = ::File.join(__FILE__[0...-3], "allocation.rb")
end
trace(&work) click to toggle source

Trace memory allocations

@api public

# File lib/benchmark/malloc.rb, line 24
def self.trace(&work)
  Malloc.new.run(&work)
end

Public Instance Methods

check_running() click to toggle source

@api private

# File lib/benchmark/malloc.rb, line 38
def check_running
  unless @running
    raise Error, "not started yet"
  end
end
run() { || ... } click to toggle source

Gather allocation stats of Ruby code inside of the block

@example

malloc = Malloc.new
malloc.run { ... }

@return [Malloc::Result]

@api public

# File lib/benchmark/malloc.rb, line 104
def run(&work)
  start
  warmup.times { yield }

  begin
    yield
  rescue Exception
    ObjectSpace.trace_object_allocations_stop
    GC.enable
    raise
  else
    stop
  end
end
start() click to toggle source

Start allocation tracing

@example

malloc = Malloc.new
malloc.start

@api public

# File lib/benchmark/malloc.rb, line 51
def start
  if @running
    raise Error, "already running"
  end

  GC.start
  GC.disable
  @generation = GC.count
  @running = true
  @existing_ids = []
  ObjectSpace.each_object do |object|
    @existing_ids << object.__id__
  end
  ObjectSpace.trace_object_allocations_start
end
stop() click to toggle source

Stop allocation tracing if currently running

@example

Malloc.stop

@api public

# File lib/benchmark/malloc.rb, line 73
def stop
  check_running

  ObjectSpace.trace_object_allocations_stop
  allocated = collect_allocations
  retained  = []
  @running  = false
  GC.enable
  GC.start

  ObjectSpace.each_object do |object|
    next unless ObjectSpace.allocation_generation(object) == generation
    next unless allocated.key?(object.__id__)
    retained << allocated[object.__id__]
  end

  ObjectSpace.trace_object_allocations_clear

  AllocationResult.new(AllocationSet.new(allocated.values),
                        AllocationSet.new(retained))
end

Private Instance Methods

collect_allocations() click to toggle source

@api private

# File lib/benchmark/malloc.rb, line 122
def collect_allocations
  allocations = {}
  ObjectSpace.each_object do |object|
    next unless ObjectSpace.allocation_generation(object) == generation
    next if ObjectSpace.allocation_sourcefile(object).nil?
    next if ObjectSpace.allocation_sourcefile(object) == __FILE__
    next if ObjectSpace.allocation_sourcefile(object) == @alloc_path
    next if @existing_ids.include?(object.__id__)

    allocations[object.__id__] = Allocation.new(object)
  end
  allocations
end