@@ -388,7 +388,7 @@ int relative_index_power2_free_space (size_t power2)
388388
389389#ifdef BACKGROUND_GC
390390uint32_t bgc_alloc_spin_count = 140;
391- uint32_t bgc_alloc_spin_count_loh = 16;
391+ uint32_t bgc_alloc_spin_count_uoh = 16;
392392uint32_t bgc_alloc_spin = 2;
393393
394394inline
@@ -2657,13 +2657,10 @@ size_t gc_heap::end_loh_size = 0;
26572657size_t gc_heap::bgc_begin_poh_size = 0;
26582658size_t gc_heap::end_poh_size = 0;
26592659
2660+ size_t gc_heap::uoh_a_no_bgc[uoh_generation_count] = {};
2661+ size_t gc_heap::uoh_a_bgc_marking[uoh_generation_count] = {};
2662+ size_t gc_heap::uoh_a_bgc_planning[uoh_generation_count] = {};
26602663#ifdef BGC_SERVO_TUNING
2661- uint64_t gc_heap::loh_a_no_bgc = 0;
2662-
2663- uint64_t gc_heap::loh_a_bgc_marking = 0;
2664-
2665- uint64_t gc_heap::loh_a_bgc_planning = 0;
2666-
26672664size_t gc_heap::bgc_maxgen_end_fl_size = 0;
26682665#endif //BGC_SERVO_TUNING
26692666
@@ -2794,9 +2791,9 @@ FinalizerWorkItem* gc_heap::finalizer_work;
27942791BOOL gc_heap::proceed_with_gc_p = FALSE;
27952792GCSpinLock gc_heap::gc_lock;
27962793
2797- #ifdef BGC_SERVO_TUNING
2798- uint64_t gc_heap::total_loh_a_last_bgc = 0;
2799- #endif //BGC_SERVO_TUNING
2794+ #ifdef BACKGROUND_GC
2795+ uint64_t gc_heap::total_uoh_a_last_bgc = 0;
2796+ #endif //BACKGROUND_GC
28002797
28012798#ifdef USE_REGIONS
28022799region_free_list gc_heap::global_regions_to_decommit[count_free_region_kinds];
@@ -15039,10 +15036,13 @@ gc_heap::init_gc_heap (int h_number)
1503915036 make_mark_stack(arr);
1504015037
1504115038#ifdef BACKGROUND_GC
15039+ for (int i = uoh_start_generation; i < total_generation_count; i++)
15040+ {
15041+ uoh_a_no_bgc[i - uoh_start_generation] = 0;
15042+ uoh_a_bgc_marking[i - uoh_start_generation] = 0;
15043+ uoh_a_bgc_planning[i - uoh_start_generation] = 0;
15044+ }
1504215045#ifdef BGC_SERVO_TUNING
15043- loh_a_no_bgc = 0;
15044- loh_a_bgc_marking = 0;
15045- loh_a_bgc_planning = 0;
1504615046 bgc_maxgen_end_fl_size = 0;
1504715047#endif //BGC_SERVO_TUNING
1504815048 freeable_soh_segment = 0;
@@ -18424,6 +18424,29 @@ bool gc_heap::should_retry_other_heap (int gen_number, size_t size)
1842418424 }
1842518425}
1842618426
18427+ void gc_heap::bgc_record_uoh_allocation(int gen_number, size_t size)
18428+ {
18429+ assert((gen_number >= uoh_start_generation) && (gen_number < total_generation_count));
18430+
18431+ if (gc_heap::background_running_p())
18432+ {
18433+ background_uoh_alloc_count++;
18434+
18435+ if (current_c_gc_state == c_gc_state_planning)
18436+ {
18437+ uoh_a_bgc_planning[gen_number - uoh_start_generation] += size;
18438+ }
18439+ else
18440+ {
18441+ uoh_a_bgc_marking[gen_number - uoh_start_generation] += size;
18442+ }
18443+ }
18444+ else
18445+ {
18446+ uoh_a_no_bgc[gen_number - uoh_start_generation] += size;
18447+ }
18448+ }
18449+
1842718450allocation_state gc_heap::allocate_uoh (int gen_number,
1842818451 size_t size,
1842918452 alloc_context* acontext,
@@ -18446,26 +18469,12 @@ allocation_state gc_heap::allocate_uoh (int gen_number,
1844618469#endif //RECORD_LOH_STATE
1844718470
1844818471#ifdef BACKGROUND_GC
18472+ bgc_record_uoh_allocation(gen_number, size);
18473+
1844918474 if (gc_heap::background_running_p())
1845018475 {
18451- #ifdef BGC_SERVO_TUNING
18452- bool planning_p = (current_c_gc_state == c_gc_state_planning);
18453- #endif //BGC_SERVO_TUNING
18454-
18455- background_uoh_alloc_count++;
18456- //if ((background_loh_alloc_count % bgc_alloc_spin_count_loh) == 0)
18476+ //if ((background_uoh_alloc_count % bgc_alloc_spin_count_uoh) == 0)
1845718477 {
18458- #ifdef BGC_SERVO_TUNING
18459- if (planning_p)
18460- {
18461- loh_a_bgc_planning += size;
18462- }
18463- else
18464- {
18465- loh_a_bgc_marking += size;
18466- }
18467- #endif //BGC_SERVO_TUNING
18468-
1846918478 int spin_for_allocation = (gen_number == loh_generation) ?
1847018479 bgc_loh_allocate_spin() :
1847118480 bgc_poh_allocate_spin();
@@ -18491,12 +18500,6 @@ allocation_state gc_heap::allocate_uoh (int gen_number,
1849118500 }
1849218501 }
1849318502 }
18494- #ifdef BGC_SERVO_TUNING
18495- else
18496- {
18497- loh_a_no_bgc += size;
18498- }
18499- #endif //BGC_SERVO_TUNING
1850018503#endif //BACKGROUND_GC
1850118504
1850218505 gc_reason gr = reason_oos_loh;
@@ -40624,7 +40627,7 @@ void gc_heap::bgc_tuning::record_and_adjust_bgc_end()
4062440627
4062540628 calculate_tuning (max_generation, true);
4062640629
40627- if (total_loh_a_last_bgc > 0)
40630+ if (total_uoh_a_last_bgc > 0)
4062840631 {
4062940632 calculate_tuning (loh_generation, true);
4063040633 }
@@ -45821,9 +45824,6 @@ void gc_heap::background_sweep()
4582145824 concurrent_print_time_delta ("Sw");
4582245825 dprintf (2, ("---- (GC%zu)Background Sweep Phase ----", VolatileLoad(&settings.gc_index)));
4582345826
45824- //block concurrent allocation for large objects
45825- dprintf (3, ("lh state: planning"));
45826-
4582745827 for (int i = 0; i <= max_generation; i++)
4582845828 {
4582945829 generation* gen_to_reset = generation_of (i);
@@ -45872,6 +45872,9 @@ void gc_heap::background_sweep()
4587245872 sweep_ro_segments();
4587345873#endif //FEATURE_BASICFREEZE
4587445874
45875+ dprintf (3, ("lh state: planning"));
45876+
45877+ // Multiple threads may reach here. This conditional partially avoids multiple volatile writes.
4587545878 if (current_c_gc_state != c_gc_state_planning)
4587645879 {
4587745880 current_c_gc_state = c_gc_state_planning;
@@ -45902,9 +45905,7 @@ void gc_heap::background_sweep()
4590245905
4590345906 if (heap_number == 0)
4590445907 {
45905- #ifdef BGC_SERVO_TUNING
45906- get_and_reset_loh_alloc_info();
45907- #endif //BGC_SERVO_TUNING
45908+ get_and_reset_uoh_alloc_info();
4590845909 uint64_t suspended_end_ts = GetHighPrecisionTimeStamp();
4590945910 last_bgc_info[last_bgc_info_index].pause_durations[1] = (size_t)(suspended_end_ts - suspended_start_time);
4591045911 total_suspended_time += last_bgc_info[last_bgc_info_index].pause_durations[1];
@@ -46233,6 +46234,7 @@ void gc_heap::background_sweep()
4623346234 concurrent_print_time_delta ("Swe SOH");
4623446235 FIRE_EVENT(BGC1stSweepEnd, 0);
4623546236
46237+ //block concurrent allocation for UOH objects
4623646238 enter_spin_lock (&more_space_lock_uoh);
4623746239 add_saved_spinlock_info (true, me_acquire, mt_bgc_uoh_sweep, msl_entered);
4623846240
@@ -46288,6 +46290,15 @@ void gc_heap::background_sweep()
4628846290 // be accurate.
4628946291 compute_new_dynamic_data (max_generation);
4629046292
46293+ // We also need to adjust size_before for UOH allocations that occurred during sweeping.
46294+ gc_history_per_heap* current_gc_data_per_heap = get_gc_data_per_heap();
46295+ for (int i = uoh_start_generation; i < total_generation_count; i++)
46296+ {
46297+ assert(uoh_a_bgc_marking[i - uoh_start_generation] == 0);
46298+ assert(uoh_a_no_bgc[i - uoh_start_generation] == 0);
46299+ current_gc_data_per_heap->gen_data[i].size_before += uoh_a_bgc_planning[i - uoh_start_generation];
46300+ }
46301+
4629146302#ifdef DOUBLY_LINKED_FL
4629246303 current_bgc_state = bgc_not_in_process;
4629346304
@@ -50257,17 +50268,15 @@ void gc_heap::check_and_adjust_bgc_tuning (int gen_number, size_t physical_size,
5025750268 }
5025850269 }
5025950270}
50271+ #endif //BGC_SERVO_TUNING
5026050272
50261- void gc_heap::get_and_reset_loh_alloc_info ()
50273+ void gc_heap::get_and_reset_uoh_alloc_info ()
5026250274{
50263- if (!bgc_tuning::enable_fl_tuning)
50264- return;
50275+ total_uoh_a_last_bgc = 0;
5026550276
50266- total_loh_a_last_bgc = 0;
50267-
50268- uint64_t total_loh_a_no_bgc = 0;
50269- uint64_t total_loh_a_bgc_marking = 0;
50270- uint64_t total_loh_a_bgc_planning = 0;
50277+ uint64_t total_uoh_a_no_bgc = 0;
50278+ uint64_t total_uoh_a_bgc_marking = 0;
50279+ uint64_t total_uoh_a_bgc_planning = 0;
5027150280#ifdef MULTIPLE_HEAPS
5027250281 for (int i = 0; i < gc_heap::n_heaps; i++)
5027350282 {
@@ -50276,21 +50285,32 @@ void gc_heap::get_and_reset_loh_alloc_info()
5027650285 {
5027750286 gc_heap* hp = pGenGCHeap;
5027850287#endif //MULTIPLE_HEAPS
50279- total_loh_a_no_bgc += hp->loh_a_no_bgc;
50280- hp->loh_a_no_bgc = 0;
50281- total_loh_a_bgc_marking += hp->loh_a_bgc_marking;
50282- hp->loh_a_bgc_marking = 0;
50283- total_loh_a_bgc_planning += hp->loh_a_bgc_planning;
50284- hp->loh_a_bgc_planning = 0;
50288+
50289+ // We need to adjust size_before for UOH allocations that occurred during marking
50290+ // before we lose the values here.
50291+ gc_history_per_heap* current_gc_data_per_heap = hp->get_gc_data_per_heap();
50292+ // loh/poh_a_bgc_planning should be the same as they were when init_records set size_before.
50293+ for (int i = uoh_start_generation; i < total_generation_count; i++)
50294+ {
50295+ current_gc_data_per_heap->gen_data[i].size_before += hp->uoh_a_bgc_marking[i - uoh_start_generation];
50296+
50297+ total_uoh_a_no_bgc += hp->uoh_a_no_bgc[i - uoh_start_generation];
50298+ hp->uoh_a_no_bgc[i - uoh_start_generation] = 0;
50299+
50300+ total_uoh_a_bgc_marking += hp->uoh_a_bgc_marking[i - uoh_start_generation];
50301+ hp->uoh_a_bgc_marking[i - uoh_start_generation] = 0;
50302+
50303+ total_uoh_a_bgc_planning += hp->uoh_a_bgc_planning[i - uoh_start_generation];
50304+ hp->uoh_a_bgc_planning[i - uoh_start_generation] = 0;
50305+ }
5028550306 }
5028650307 dprintf (2, ("LOH alloc: outside bgc: %zd; bm: %zd; bp: %zd",
50287- total_loh_a_no_bgc ,
50288- total_loh_a_bgc_marking ,
50289- total_loh_a_bgc_planning ));
50308+ total_uoh_a_no_bgc ,
50309+ total_uoh_a_bgc_marking ,
50310+ total_uoh_a_bgc_planning ));
5029050311
50291- total_loh_a_last_bgc = total_loh_a_no_bgc + total_loh_a_bgc_marking + total_loh_a_bgc_planning ;
50312+ total_uoh_a_last_bgc = total_uoh_a_no_bgc + total_uoh_a_bgc_marking + total_uoh_a_bgc_planning ;
5029250313}
50293- #endif //BGC_SERVO_TUNING
5029450314
5029550315bool gc_heap::is_pm_ratio_exceeded()
5029650316{
0 commit comments