Skip to content

Commit

Permalink
Remove dependency on memory_profiler
Browse files Browse the repository at this point in the history
  • Loading branch information
kputnam committed Sep 17, 2019
1 parent 704589a commit 7d0a032
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 23 deletions.
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,4 @@ group :development do
gem "benchmark-ips"# ""
gem "simplecov"# ""
gem "simplecov-inline-html" if RUBY_VERSION >= "2.4"
gem "memory_profiler" if RUBY_VERSION >= "2.3.8"
end
4 changes: 4 additions & 0 deletions lib/stupidedi/position/no_position.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ def inspect
def advance(input)
self
end

def ===(other)
equal?(other)
end
end
end
end
17 changes: 12 additions & 5 deletions lib/stupidedi/reader/substring.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,11 @@ def match?(pattern, offset=0, anchorless: false)
#
# @return [Integer]
def =~(pattern)
m, offset = _match(pattern, 0)
m and m.begin(0) + offset
if result = _match(pattern, 0)
m = result[0]
offset = result[1]
m and m.begin(0) + offset
end
end

# @group Search
Expand All @@ -108,8 +111,11 @@ def index(other, offset=0, anchorless: false)
return nil if offset > @length

if other_ = Regexp.try_convert(other)
m, offset = _match(other_, offset, anchorless)
m and m.begin(0) + offset
if result = _match(other_, offset, anchorless)
m = result[0]
offset = result[1]
m and m.begin(0) + offset
end
elsif other_ = String.try_convert(other)
n = @storage.index(other_, @offset + offset)
n - @offset if n and n + other_.length <= @offset + @length
Expand Down Expand Up @@ -151,7 +157,8 @@ def rindex(other, offset=@length-1)
def count(other)
other = _convert(String, other)
length = other.length
count, offset = 0, @offset
count = 0
offset = @offset

while true
offset = @storage.index(other, offset)
Expand Down
5 changes: 3 additions & 2 deletions spec/lib/stupidedi/reader/pointer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ def suffix(pointer)
specify { expect(pointer("abc")).to be_a(Stupidedi::Reader::Pointer) }

allocation do
storage = "X"
expect{ pointer(storage) }.to allocate(Stupidedi::Reader::Substring => 1)
ignore = nil
storage = [1,1,1]
expect{ ignore = pointer(storage) }.to allocate(Stupidedi::Reader::Pointer => 1)
end
end

Expand Down
12 changes: 6 additions & 6 deletions spec/lib/stupidedi/reader/substring_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -774,12 +774,12 @@ def matchp(num_calls)
let(:regexp_o) { /..+/ }
let(:regexp_x) { /xxx/ }

#it "works like String#=~" do
# substrings(lower.length) do |idx, len|
# expect(lower_ptr[idx, len] =~ regexp_o).to eq(lower[idx, len] =~ regexp_o)
# expect(lower_ptr[idx, len] =~ regexp_x).to eq(lower[idx, len] =~ regexp_x)
# end
#end
it "works like String#=~" do
substrings(lower.length) do |idx, len|
expect(lower_ptr[idx, len] =~ regexp_o).to eq(lower[idx, len] =~ regexp_o)
expect(lower_ptr[idx, len] =~ regexp_x).to eq(lower[idx, len] =~ regexp_x)
end
end

allocation do
a = lower_ptr.drop(3).take(3)
Expand Down
5 changes: 0 additions & 5 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@
rescue LoadError
end

begin
require "memory_profiler"
rescue LoadError
end

require "stupidedi"
require "ostruct"
require "pp"
Expand Down
8 changes: 4 additions & 4 deletions spec/support/matchers/allocation_matchers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def initialize(op, limits)

@op, @limits = op, Hash[limits.map{|k,v| [k.to_s, v] }]

raise "can't load memory_profiler" unless defined? MemoryProfiler
raise "can't load memory_profiler" unless defined? MemProf
end

def description
Expand Down Expand Up @@ -79,9 +79,9 @@ def measure(target)
opts = {trace: @limits.keys.map{|c| Object.const_get(c)}}
opts.delete(:trace) if @strict

report = MemoryProfiler.report(opts, &target)
result = report.allocated_objects_by_class
result.inject({}){|memo, x| memo.update(x[:data] => x[:count]) }
report = MemProf.report(opts, &target)
result = report.allocations_by_class
result.inject({}){|memo, (k,v)| memo.update(k.name => v[:count]) }
end
end
end
117 changes: 117 additions & 0 deletions spec/support/memprof.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
require "objspace"

class MemProf
def initialize(options)
@trace = options[:trace]
@ignore = options[:ignore]
@allow = options[:allow]
@retain = false
end

def run(&block)
start
begin
yield
rescue Exception
ObjectSpace.trace_object_allocations_stop
GC.enable if @retain
raise
else
stop
end
end

private

def start
if @retain
GC.start
GC.start
GC.start
GC.disable
end

@generation = GC.count
ObjectSpace.trace_object_allocations_start
end

def stop
ObjectSpace.trace_object_allocations_stop

allocated = allocations
retained = Hash.new

if @retain
GC.enable
GC.start
GC.start
GC.start

ObjectSpace.each_object do |o|
next if ObjectSpace.allocation_generation(o) != @generation
match = allocations[o.__id__]
retained[o.__id__] = match if match
end
end

ObjectSpace.trace_object_allocations_clear
Results.new(allocated, retained)
end

def allocations
results = Hash.new.compare_by_identity
klass = Kernel.instance_method(:class)

ObjectSpace.each_object do |o|
next if ObjectSpace.allocation_generation(o) != @generation

file = ObjectSpace.allocation_sourcefile(o).to_s
next if @ignore and @ignore.match?(file)
next if @allow and not @allow.match?(file)

klass_ = klass.bind(o).call
next if @trace and not @trace.match?(klass_)

line = ObjectSpace.allocation_sourceline(o)
method = ObjectSpace.allocation_method_id(o)
bytes = ObjectSpace.memsize_of(o)

results[o.__id__] = Stat.new(klass_, file, line, [file, line], method, bytes)
end

results
end
end

MemProf::Stat = Struct.new(:klass, :file, :line, :location, :method, :bytes)

class MemProf::Results
def initialize(allocated, retained)
@allocated = allocated.values
@retained = retained.values
end

def allocations_by_class
Hash[@allocated.group_by(&:klass).map do |klass, stats|
[klass, {data: klass, count: stats.length, bytes: stats.sum(&:bytes)}]
end]
end

def allocations_by_method
Hash[@allocated.group_by(&:method).map do |klass, stats|
[klass, {data: klass, count: stats.length, bytes: stats.sum(&:bytes)}]
end]
end

def allocations_by_location
Hash[@allocated.group_by(&:location).map do |klass, stats|
[klass, {data: klass, count: stats.length, bytes: stats.sum(&:bytes)}]
end]
end
end

class << MemProf
def report(options={}, &block)
new(options).run(&block)
end
end

0 comments on commit 7d0a032

Please sign in to comment.