Speedup test_shape.rb
Many tests start by exhausting all shapes, which is a slow process. By exposing a method to directly move the bump allocator forward we cut test runtime in half. Before: ``` Finished tests in 1.544756s ``` After: ``` Finished tests in 0.759733s, ```
This commit is contained in:
parent
0745c0c5ef
commit
2d7fb9c2fa
10
shape.c
10
shape.c
@ -1057,6 +1057,15 @@ rb_shape_shapes_available(VALUE self)
|
|||||||
return INT2NUM(MAX_SHAPE_ID - (GET_SHAPE_TREE()->next_shape_id - 1));
|
return INT2NUM(MAX_SHAPE_ID - (GET_SHAPE_TREE()->next_shape_id - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
rb_shape_exhaust(int argc, VALUE *argv, VALUE self)
|
||||||
|
{
|
||||||
|
rb_check_arity(argc, 0, 1);
|
||||||
|
int offset = argc == 1 ? NUM2INT(argv[0]) : 0;
|
||||||
|
GET_SHAPE_TREE()->next_shape_id = MAX_SHAPE_ID - offset;
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
VALUE rb_obj_shape(rb_shape_t* shape);
|
VALUE rb_obj_shape(rb_shape_t* shape);
|
||||||
|
|
||||||
static enum rb_id_table_iterator_result collect_keys_and_values(ID key, VALUE value, void *ref)
|
static enum rb_id_table_iterator_result collect_keys_and_values(ID key, VALUE value, void *ref)
|
||||||
@ -1239,5 +1248,6 @@ Init_shape(void)
|
|||||||
rb_define_singleton_method(rb_cShape, "of", rb_shape_debug_shape, 1);
|
rb_define_singleton_method(rb_cShape, "of", rb_shape_debug_shape, 1);
|
||||||
rb_define_singleton_method(rb_cShape, "root_shape", rb_shape_root_shape, 0);
|
rb_define_singleton_method(rb_cShape, "root_shape", rb_shape_root_shape, 0);
|
||||||
rb_define_singleton_method(rb_cShape, "shapes_available", rb_shape_shapes_available, 0);
|
rb_define_singleton_method(rb_cShape, "shapes_available", rb_shape_shapes_available, 0);
|
||||||
|
rb_define_singleton_method(rb_cShape, "exhaust_shapes", rb_shape_exhaust, -1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -191,12 +191,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
attr_reader :very_unique
|
attr_reader :very_unique
|
||||||
end
|
end
|
||||||
|
|
||||||
obj = Object.new
|
RubyVM::Shape.exhaust_shapes
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
obj.instance_variable_set(:"@a#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
(RubyVM::Shape::SHAPE_MAX_VARIATIONS * 2).times do
|
(RubyVM::Shape::SHAPE_MAX_VARIATIONS * 2).times do
|
||||||
TooComplex.new.instance_variable_set(:"@unique_#{_1}", 1)
|
TooComplex.new.instance_variable_set(:"@unique_#{_1}", 1)
|
||||||
@ -216,13 +211,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
begin;
|
begin;
|
||||||
class Hi; end
|
class Hi; end
|
||||||
|
RubyVM::Shape.exhaust_shapes(3)
|
||||||
obj = Hi.new
|
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 2
|
|
||||||
obj.instance_variable_set(:"@a#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
obj = Hi.new
|
obj = Hi.new
|
||||||
i = 0
|
i = 0
|
||||||
@ -243,26 +232,16 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
@a = 1
|
@a = 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# Try to run out of shapes
|
RubyVM::Shape.exhaust_shapes
|
||||||
o = Object.new
|
|
||||||
i = 0
|
A.new
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
A.new
|
|
||||||
end
|
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_run_out_of_shape_for_class_ivar
|
def test_run_out_of_shape_for_class_ivar
|
||||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
begin;
|
begin;
|
||||||
i = 0
|
RubyVM::Shape.exhaust_shapes
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
c = Class.new
|
|
||||||
c.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
c = Class.new
|
c = Class.new
|
||||||
c.instance_variable_set(:@a, 1)
|
c.instance_variable_set(:@a, 1)
|
||||||
@ -282,12 +261,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
begin;
|
begin;
|
||||||
[].instance_variable_set(:@a, 1)
|
[].instance_variable_set(:@a, 1)
|
||||||
|
|
||||||
i = 0
|
RubyVM::Shape.exhaust_shapes
|
||||||
o = Object.new
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
ary = 10.times.map { [] }
|
ary = 10.times.map { [] }
|
||||||
|
|
||||||
@ -302,12 +276,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
def test_run_out_of_shape_for_module_ivar
|
def test_run_out_of_shape_for_module_ivar
|
||||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
begin;
|
begin;
|
||||||
o = Object.new
|
RubyVM::Shape.exhaust_shapes
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
module Foo
|
module Foo
|
||||||
@a = 1
|
@a = 1
|
||||||
@ -321,12 +290,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
def test_run_out_of_shape_for_class_cvar
|
def test_run_out_of_shape_for_class_cvar
|
||||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
begin;
|
begin;
|
||||||
i = 0
|
RubyVM::Shape.exhaust_shapes
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
c = Class.new
|
|
||||||
c.class_variable_set(:"@@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
c = Class.new
|
c = Class.new
|
||||||
|
|
||||||
@ -348,13 +312,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
class TooComplex < Hash
|
class TooComplex < Hash
|
||||||
end
|
end
|
||||||
|
|
||||||
# Try to run out of shapes
|
RubyVM::Shape.exhaust_shapes
|
||||||
o = Object.new
|
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
tc = TooComplex.new
|
tc = TooComplex.new
|
||||||
tc.instance_variable_set(:@a, 1)
|
tc.instance_variable_set(:@a, 1)
|
||||||
@ -387,15 +345,10 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
a = Hi.new
|
a = Hi.new
|
||||||
|
|
||||||
# Try to run out of shapes
|
# Try to run out of shapes
|
||||||
o = Object.new
|
RubyVM::Shape.exhaust_shapes
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_equal 1,a.transition
|
assert_equal 1, a.transition
|
||||||
assert_equal 1,a.transition
|
assert_equal 1, a.transition
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -409,12 +362,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
o = Object.new
|
RubyVM::Shape.exhaust_shapes
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
a = A.new
|
a = A.new
|
||||||
assert_equal true, a.instance_variable_defined?(:@a)
|
assert_equal true, a.instance_variable_defined?(:@a)
|
||||||
@ -424,12 +372,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
def test_run_out_of_shape_instance_variable_defined_on_module
|
def test_run_out_of_shape_instance_variable_defined_on_module
|
||||||
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
|
||||||
begin;
|
begin;
|
||||||
o = Object.new
|
RubyVM::Shape.exhaust_shapes
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
module A
|
module A
|
||||||
@a = @b = @c = @d = 1
|
@a = @b = @c = @d = 1
|
||||||
@ -445,12 +388,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
o = Object.new
|
o = Object.new
|
||||||
10.times { |i| o.instance_variable_set(:"@a#{i}", i) }
|
10.times { |i| o.instance_variable_set(:"@a#{i}", i) }
|
||||||
|
|
||||||
i = 0
|
RubyVM::Shape.exhaust_shapes
|
||||||
a = Object.new
|
|
||||||
while RubyVM::Shape.shapes_available > 2
|
|
||||||
a.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
o.remove_instance_variable(:@a0)
|
o.remove_instance_variable(:@a0)
|
||||||
(1...10).each do |i|
|
(1...10).each do |i|
|
||||||
@ -471,12 +409,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
|
|
||||||
a = A.new
|
a = A.new
|
||||||
|
|
||||||
o = Object.new
|
RubyVM::Shape.exhaust_shapes
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
a.remove_instance_variable(:@b)
|
a.remove_instance_variable(:@b)
|
||||||
assert_nil a.b
|
assert_nil a.b
|
||||||
@ -506,12 +439,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
|
|
||||||
a = A.new
|
a = A.new
|
||||||
|
|
||||||
o = Object.new
|
RubyVM::Shape.exhaust_shapes
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 1
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
a.dup
|
a.dup
|
||||||
end;
|
end;
|
||||||
@ -522,12 +450,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
o = []
|
o = []
|
||||||
o.instance_variable_set(:@a, 1)
|
o.instance_variable_set(:@a, 1)
|
||||||
|
|
||||||
i = 0
|
RubyVM::Shape.exhaust_shapes
|
||||||
o = Object.new
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
ary = 1_000_000.times.map { [] }
|
ary = 1_000_000.times.map { [] }
|
||||||
begin;
|
begin;
|
||||||
@ -546,12 +469,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
begin;
|
begin;
|
||||||
class Hi; end
|
class Hi; end
|
||||||
|
|
||||||
obj = Hi.new
|
RubyVM::Shape.exhaust_shapes(2)
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 2
|
|
||||||
obj.instance_variable_set(:"@a#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
obj = Module.new
|
obj = Module.new
|
||||||
3.times do
|
3.times do
|
||||||
@ -571,12 +489,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
begin;
|
begin;
|
||||||
class Hi; end
|
class Hi; end
|
||||||
|
|
||||||
obj = Hi.new
|
RubyVM::Shape.exhaust_shapes(2)
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 2
|
|
||||||
obj.instance_variable_set(:"@a#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
obj = Object.new
|
obj = Object.new
|
||||||
i = 0
|
i = 0
|
||||||
@ -748,12 +661,7 @@ class TestShapes < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
assert_equal [0, 1, 2, 3, 4], ivars
|
assert_equal [0, 1, 2, 3, 4], ivars
|
||||||
|
|
||||||
o = Object.new
|
RubyVM::Shape.exhaust_shapes
|
||||||
i = 0
|
|
||||||
while RubyVM::Shape.shapes_available > 0
|
|
||||||
o.instance_variable_set(:"@i#{i}", 1)
|
|
||||||
i += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
object.remove_instance_variable(:@ivar_2)
|
object.remove_instance_variable(:@ivar_2)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user