[ruby-core:95033] [Ruby master Misc#16124] Let the transient heap belong to objspace
From:
lourens@...
Date:
2019-09-22 14:36:32 UTC
List:
ruby-core #95033
Issue #16124 has been updated by methodmissing (Lourens Naud=E9).
nobu (Nobuyoshi Nakada) wrote:
> I'm positive about this, except for the performance.
> Do you have any numbers?
Using the rdoc gc bench tooling Koichi used in https://bugs.ruby-lang.org/i=
ssues/14858, it's difficult to get consistent results between this change a=
nd master.
Master:
```
lourens@CarbonX1:~/src/ruby/trunk$ make gcbench-rdoc
Script: ./benchmark/gc/rdoc.rb
{:count=3D>137,
:heap_allocated_pages=3D>10124,
:heap_sorted_length=3D>10124,
:heap_allocatable_pages=3D>0,
:heap_available_slots=3D>4126494,
:heap_live_slots=3D>4117009,
:heap_free_slots=3D>9485,
:heap_final_slots=3D>0,
:heap_marked_slots=3D>2396930,
:heap_eden_pages=3D>10124,
:heap_tomb_pages=3D>0,
:total_allocated_pages=3D>10124,
:total_freed_pages=3D>0,
:total_allocated_objects=3D>24630985,
:total_freed_objects=3D>20513976,
:malloc_increase_bytes=3D>23046392,
:malloc_increase_bytes_limit=3D>32225676,
:minor_gc_count=3D>113,
:object_id_collisions=3D>0,
:major_gc_count=3D>24,
:remembered_wb_unprotected_objects=3D>2482,
:remembered_wb_unprotected_objects_limit=3D>4964,
:old_objects=3D>2387069,
:old_objects_limit=3D>4774138,
:oldmalloc_increase_bytes=3D>48011656,
:oldmalloc_increase_bytes_limit=3D>41096563}
ruby 2.7.0dev (2019-09-22T07:39:47Z master 2272efa463) [x86_64-linux] ["USE=
_RGENGC", "RGENGC_DEBUG", "RGENGC_ESTIMATE_OLDMALLOC", "GC_ENABLE_LAZY_SWEE=
P"]
./benchmark/gc/rdoc.rb
user system total real
18.842867 0.687732 19.530599 ( 19.722540)
GC total time (sec): 0
VmHWM: 411940 kB
Summary of rdoc on 2.7.0dev 19.722539804002736 0 137
(real time in sec, GC time in sec, GC count)
```
Objspace linked theap:
```
lourens@CarbonX1:~/src/ruby/ruby$ make gcbench-rdoc
Script: ./benchmark/gc/rdoc.rb
{:count=3D>137,
:heap_allocated_pages=3D>10122,
:heap_sorted_length=3D>10122,
:heap_allocatable_pages=3D>0,
:heap_available_slots=3D>4125809,
:heap_live_slots=3D>4116170,
:heap_free_slots=3D>9639,
:heap_final_slots=3D>0,
:heap_marked_slots=3D>2396677,
:heap_eden_pages=3D>10122,
:heap_tomb_pages=3D>0,
:total_allocated_pages=3D>10122,
:total_freed_pages=3D>0,
:total_allocated_objects=3D>24630955,
:total_freed_objects=3D>20514785,
:malloc_increase_bytes=3D>23055352,
:malloc_increase_bytes_limit=3D>32225676,
:minor_gc_count=3D>113,
:object_id_collisions=3D>0,
:major_gc_count=3D>24,
:remembered_wb_unprotected_objects=3D>2482,
:remembered_wb_unprotected_objects_limit=3D>4964,
:old_objects=3D>2387070,
:old_objects_limit=3D>4774140,
:oldmalloc_increase_bytes=3D>47981528,
:oldmalloc_increase_bytes_limit=3D>41096563}
ruby 2.7.0dev (2019-09-22T11:43:20Z objspace-theap 11b7839f09) [x86_64-linu=
x] ["USE_RGENGC", "RGENGC_DEBUG", "RGENGC_ESTIMATE_OLDMALLOC", "GC_ENABLE_L=
AZY_SWEEP"]
./benchmark/gc/rdoc.rb
user system total real
18.517571 0.764057 19.281628 ( 19.303723)
GC total time (sec): 0
VmHWM: 411780 kB
Summary of rdoc on 2.7.0dev 19.303723024990177 0 137
(real time in sec, GC time in sec, GC count)
```
Array specific (adapted from the original issue to include `RUBY_DESCRIPTIO=
N`):
```
p RUBY_DESCRIPTION
require 'benchmark'
N =3D 10_000_000
def n_times str, args =3D ''
eval <<-EOS
proc{|max, #{args}|
i =3D 0
while i < max
#{str}
i+=3D1
end
}
EOS
end
m =3D n_times 'ary =3D Array.new(size)', 'size'
Benchmark.bm(10){|x|
0.step(to: 16){|i|
size =3D i
x.report(size){
m.call(N, size)
}
}
}
```
`objspace-theap` branch:
```
lourens@CarbonX1:~/src/ruby/ruby$ ./miniruby -Ilib $HOME/src/theap_array.rb
"ruby 2.7.0dev (2019-09-22T11:43:20Z objspace-theap 11b7839f09) [x86_64-lin=
ux]"
user system total real
0 1.060482 0.000000 1.060482 ( 1.060477)
1 1.063371 0.000000 1.063371 ( 1.063398)
2 1.049839 0.000000 1.049839 ( 1.049846)
3 1.066307 0.000000 1.066307 ( 1.066311)
4 1.187135 0.000000 1.187135 ( 1.187147)
5 1.130953 0.000000 1.130953 ( 1.130964)
6 1.160799 0.000000 1.160799 ( 1.160805)
7 1.220265 0.000000 1.220265 ( 1.220272)
8 1.160544 0.000000 1.160544 ( 1.160554)
9 1.262271 0.000000 1.262271 ( 1.262282)
10 1.182926 0.000000 1.182926 ( 1.182933)
11 1.305176 0.000000 1.305176 ( 1.305187)
12 1.170598 0.000000 1.170598 ( 1.170605)
13 1.243933 0.000000 1.243933 ( 1.243940)
14 1.197929 0.000000 1.197929 ( 1.197955)
15 1.257225 0.000000 1.257225 ( 1.257232)
16 1.203359 0.000000 1.203359 ( 1.203365)
```
master:
```
lourens@CarbonX1:~/src/ruby/trunk$ ./miniruby -Ilib $HOME/src/theap_array.rb
"ruby 2.7.0dev (2019-09-22T07:39:47Z master 2272efa463) [x86_64-linux]"
user system total real
0 1.034709 0.000000 1.034709 ( 1.035330)
1 1.073345 0.000000 1.073345 ( 1.073350)
2 1.046693 0.000000 1.046693 ( 1.046704)
3 1.046481 0.000000 1.046481 ( 1.046487)
4 1.135405 0.000000 1.135405 ( 1.135410)
5 1.152307 0.000000 1.152307 ( 1.152308)
6 1.163179 0.000000 1.163179 ( 1.163184)
7 1.229176 0.000000 1.229176 ( 1.229193)
8 1.171530 0.000000 1.171530 ( 1.171541)
9 1.229018 0.000000 1.229018 ( 1.229023)
10 1.218360 0.000000 1.218360 ( 1.218369)
11 1.258088 0.000000 1.258088 ( 1.258093)
12 1.214547 0.000000 1.214547 ( 1.214557)
13 1.246675 0.000000 1.246675 ( 1.246693)
14 1.217621 0.000000 1.217621 ( 1.217620)
15 1.240967 0.000000 1.240967 ( 1.240972)
16 1.246610 0.000000 1.246610 ( 1.246620)
```
Optcarrot (noisy too):
```
lourens@CarbonX1:~/src/optcarrot$ benchmark-driver -e "objspace-theap::~/sr=
c/ruby/ruby/ruby -I~/src/ruby/ruby/lib -I~/src/ruby/ruby/. -I~/src/ruby/rub=
y/.ext/x86_64-linux" -e "trunk::~/src/ruby/trunk/ruby -I~/src/ruby/trunk/li=
b -I~/src/ruby/trunk/. -I~/src/ruby/trunk/.ext/x86_64-linux" --repeat-count=
24 --output=3Dall -v benchmark.yml
objspace-theap: ruby 2.7.0dev (2019-09-22T11:43:20Z objspace-theap 11b7839f=
09) [x86_64-linux]
trunk: ruby 2.7.0dev (2019-09-22T07:39:47Z master 2272efa463) [x86_64-linux]
Calculating -------------------------------------
objspace-theap trunk =
optcarrot 42.40538956057937 42.50095691198821 fps
42.98025714388297 43.19539965591333 =
43.17850049383824 43.69380960879121 =
44.34221997472645 43.75925724088885 =
45.23015773087887 43.95609333352798 =
45.60259428038163 44.30873259117270 =
45.62534786154934 44.50561054139629 =
45.69848233271295 44.74074528123102 =
45.72577876475985 44.75584411276473 =
45.82588019886050 44.90017657928921 =
45.84436354482752 44.93827167130445 =
46.72210774150135 45.32808901780013 =
46.78934236282241 45.40725425997227 =
46.83007726756269 45.50752517888226 =
46.84959507374096 45.51210655013940 =
46.93537135184541 45.51427328345052 =
47.20234803912213 45.61616028100521 =
47.36550159135397 45.90162191663695 =
47.95694822288893 46.18908487592959 =
48.00296030568151 46.19919623309980 =
49.21328383054638 46.47376631857036 =
49.23558095502081 46.85201420357048 =
49.30196173221466 47.39761548726396 =
50.07004688586536 47.70501205501753
```
----------------------------------------
Misc #16124: Let the transient heap belong to objspace
https://bugs.ruby-lang.org/issues/16124#change-81664
* Author: methodmissing (Lourens Naud=E9)
* Status: Assigned
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
As per comment from Nobu in https://github.com/ruby/ruby/pull/2303#issuecom=
ment-523248875 , I took an initial stab @ a tighter integration between obj=
space and the transient heap in https://github.com/ruby/ruby/pull/2400
### Benefits
* Multi-VM (MVM) friendly - ( vm -> objspace -> theap )
* The 32MB (current size) arena lazy allocated on ruby init is now properly=
freed on shutdown as well
* It feels strange that the evacuation from the current global theap is to =
objspace, whereas the space evacuated from is a global arena.
### Not so great
* A fast reference to a global variable `global_transient_heap` becomes a f=
unction call to `rb_objspace_get_theap()` and related pointer chasing from =
vm -> objspace -> theap
* Some internal transient heap structs moved to the header file now leaks i=
nto all other reference sites where this source file (`transient_heap.c`) a=
s previously just used for API
* I'm not sure exactly of the boundary Koichi had in mind for the GC compil=
e module and how tightly it should (or shouldn't) be coupled to the transie=
nt heap. `struct rb_objspace*` declarations elsewhere for example reveals n=
othing about the structure members for example, whereas with this PR a lot =
of transient heap internals are exposed via the header file now
* Also possible to move `transient_heap.c` into `gc.c` - I feel theap is no=
t an experimental feature anymore and has been stable for quite some time w=
ith plausible performance benefits. The downside of that is `gc.c` is quite=
dense already, but then all ruby heap management concerns belong to one co=
mpile unit.
In a similar vein the global method cache could perhaps belong to the VM in=
stance as well, effectively better alignment with MVM and also easier to ha=
ve a balanced VM setup and teardown sequence without anything left dangling=
on ruby shutdown.
Thoughts?
-- =
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=3Dunsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>