@@ -71,6 +71,7 @@ namespace rubinius {
71
71
, mature_mark_concurrent_(shared.config.gc_immix_concurrent)
72
72
, mature_gc_in_progress_(false )
73
73
, slab_size_(4096 )
74
+ , interrupt_flag_(false )
74
75
, collect_young_flag_(false )
75
76
, collect_full_flag_(false )
76
77
, shared_(vm->shared)
@@ -519,6 +520,7 @@ namespace rubinius {
519
520
if (!can_gc ()) {
520
521
collect_young_flag_ = false ;
521
522
collect_full_flag_ = false ;
523
+ interrupt_flag_ = false ;
522
524
return ;
523
525
}
524
526
@@ -543,6 +545,9 @@ namespace rubinius {
543
545
} else {
544
546
collect_young (state, &gc_data);
545
547
}
548
+
549
+ if (!collect_full_flag_) interrupt_flag_ = false ;
550
+
546
551
RUBINIUS_GC_END (0 );
547
552
}
548
553
@@ -610,12 +615,12 @@ namespace rubinius {
610
615
}
611
616
612
617
void Memory::collect_full (STATE) {
613
- timer::StopWatch<timer::milliseconds> timerx (
614
- state->vm ()->metrics ().gc .immix_concurrent_ms );
615
-
616
618
// If we're already collecting, ignore this request
617
619
if (mature_gc_in_progress_) return ;
618
620
621
+ timer::StopWatch<timer::milliseconds> timerx (
622
+ state->vm ()->metrics ().gc .immix_stop_ms );
623
+
619
624
if (state->shared ().config .memory_collection_log .value ) {
620
625
logger::write (" memory: full collection" );
621
626
}
@@ -624,21 +629,34 @@ namespace rubinius {
624
629
625
630
immix_->reset_stats ();
626
631
627
- // TODO: GC hacks hacks hacks fix fix fix.
628
- if (mature_mark_concurrent_) {
629
- memory::GCData* data = new memory::GCData (state->vm ());
630
-
631
- clear_fiber_marks (data);
632
- immix_->start_marker (state);
633
- immix_->collect_start (data);
634
- mature_gc_in_progress_ = true ;
635
- } else {
632
+ {
636
633
memory::GCData data (state->vm ());
637
634
638
635
clear_fiber_marks (&data);
639
636
immix_->collect (&data);
640
637
collect_full_finish (state, &data);
641
638
}
639
+
640
+ if (mature_mark_concurrent_) {
641
+ memory::GCData* data = new memory::GCData (state->vm ());
642
+
643
+ mature_gc_in_progress_ = true ;
644
+
645
+ immix_->collect_start (data);
646
+ immix_->start_marker (state, data);
647
+ }
648
+ }
649
+
650
+ void Memory::collect_full_restart (STATE, memory::GCData* data) {
651
+ if (state->shared ().config .memory_collection_log .value ) {
652
+ logger::write (" memory: concurrent collection restart" );
653
+ }
654
+
655
+ code_manager_.clear_marks ();
656
+
657
+ immix_->reset_stats ();
658
+
659
+ immix_->collect_start (data);
642
660
}
643
661
644
662
void Memory::collect_full_finish (STATE, memory::GCData* data) {
@@ -672,6 +690,7 @@ namespace rubinius {
672
690
}
673
691
674
692
collect_full_flag_ = false ;
693
+ interrupt_flag_ = false ;
675
694
676
695
RUBINIUS_GC_END (1 );
677
696
}
@@ -783,6 +802,15 @@ namespace rubinius {
783
802
schedule_full_collection (
784
803
" mature region allocate object" ,
785
804
state->vm ()->metrics ().gc .immix_set );
805
+
806
+ if (mature_mark_concurrent_) {
807
+ /* Spilling allocations to the Large Object Space can be costly
808
+ * because that region and collector are less efficient. To mitigate
809
+ * spilling, we sleep for a very small random interval to allow the
810
+ * concurrent marking thread to catch up and complete the GC cycle.
811
+ */
812
+ state->vm ()->blocking_suspend (state, state->vm ()->metrics ().memory .suspend_ms );
813
+ }
786
814
}
787
815
788
816
collect_flag = false ;
0 commit comments