@@ -388,7 +388,7 @@ int relative_index_power2_free_space (size_t power2)
388
388
389
389
#ifdef BACKGROUND_GC
390
390
uint32_t bgc_alloc_spin_count = 140;
391
- uint32_t bgc_alloc_spin_count_loh = 16;
391
+ uint32_t bgc_alloc_spin_count_uoh = 16;
392
392
uint32_t bgc_alloc_spin = 2;
393
393
394
394
inline
@@ -2657,13 +2657,10 @@ size_t gc_heap::end_loh_size = 0;
2657
2657
size_t gc_heap::bgc_begin_poh_size = 0;
2658
2658
size_t gc_heap::end_poh_size = 0;
2659
2659
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] = {};
2660
2663
#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
-
2667
2664
size_t gc_heap::bgc_maxgen_end_fl_size = 0;
2668
2665
#endif //BGC_SERVO_TUNING
2669
2666
@@ -2794,9 +2791,9 @@ FinalizerWorkItem* gc_heap::finalizer_work;
2794
2791
BOOL gc_heap::proceed_with_gc_p = FALSE;
2795
2792
GCSpinLock gc_heap::gc_lock;
2796
2793
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
2800
2797
2801
2798
#ifdef USE_REGIONS
2802
2799
region_free_list gc_heap::global_regions_to_decommit[count_free_region_kinds];
@@ -15039,10 +15036,13 @@ gc_heap::init_gc_heap (int h_number)
15039
15036
make_mark_stack(arr);
15040
15037
15041
15038
#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
+ }
15042
15045
#ifdef BGC_SERVO_TUNING
15043
- loh_a_no_bgc = 0;
15044
- loh_a_bgc_marking = 0;
15045
- loh_a_bgc_planning = 0;
15046
15046
bgc_maxgen_end_fl_size = 0;
15047
15047
#endif //BGC_SERVO_TUNING
15048
15048
freeable_soh_segment = 0;
@@ -18424,6 +18424,29 @@ bool gc_heap::should_retry_other_heap (int gen_number, size_t size)
18424
18424
}
18425
18425
}
18426
18426
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
+
18427
18450
allocation_state gc_heap::allocate_uoh (int gen_number,
18428
18451
size_t size,
18429
18452
alloc_context* acontext,
@@ -18446,26 +18469,12 @@ allocation_state gc_heap::allocate_uoh (int gen_number,
18446
18469
#endif //RECORD_LOH_STATE
18447
18470
18448
18471
#ifdef BACKGROUND_GC
18472
+ bgc_record_uoh_allocation(gen_number, size);
18473
+
18449
18474
if (gc_heap::background_running_p())
18450
18475
{
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)
18457
18477
{
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
-
18469
18478
int spin_for_allocation = (gen_number == loh_generation) ?
18470
18479
bgc_loh_allocate_spin() :
18471
18480
bgc_poh_allocate_spin();
@@ -18491,12 +18500,6 @@ allocation_state gc_heap::allocate_uoh (int gen_number,
18491
18500
}
18492
18501
}
18493
18502
}
18494
- #ifdef BGC_SERVO_TUNING
18495
- else
18496
- {
18497
- loh_a_no_bgc += size;
18498
- }
18499
- #endif //BGC_SERVO_TUNING
18500
18503
#endif //BACKGROUND_GC
18501
18504
18502
18505
gc_reason gr = reason_oos_loh;
@@ -40624,7 +40627,7 @@ void gc_heap::bgc_tuning::record_and_adjust_bgc_end()
40624
40627
40625
40628
calculate_tuning (max_generation, true);
40626
40629
40627
- if (total_loh_a_last_bgc > 0)
40630
+ if (total_uoh_a_last_bgc > 0)
40628
40631
{
40629
40632
calculate_tuning (loh_generation, true);
40630
40633
}
@@ -45821,9 +45824,6 @@ void gc_heap::background_sweep()
45821
45824
concurrent_print_time_delta ("Sw");
45822
45825
dprintf (2, ("---- (GC%zu)Background Sweep Phase ----", VolatileLoad(&settings.gc_index)));
45823
45826
45824
- //block concurrent allocation for large objects
45825
- dprintf (3, ("lh state: planning"));
45826
-
45827
45827
for (int i = 0; i <= max_generation; i++)
45828
45828
{
45829
45829
generation* gen_to_reset = generation_of (i);
@@ -45872,6 +45872,9 @@ void gc_heap::background_sweep()
45872
45872
sweep_ro_segments();
45873
45873
#endif //FEATURE_BASICFREEZE
45874
45874
45875
+ dprintf (3, ("lh state: planning"));
45876
+
45877
+ // Multiple threads may reach here. This conditional partially avoids multiple volatile writes.
45875
45878
if (current_c_gc_state != c_gc_state_planning)
45876
45879
{
45877
45880
current_c_gc_state = c_gc_state_planning;
@@ -45902,9 +45905,7 @@ void gc_heap::background_sweep()
45902
45905
45903
45906
if (heap_number == 0)
45904
45907
{
45905
- #ifdef BGC_SERVO_TUNING
45906
- get_and_reset_loh_alloc_info();
45907
- #endif //BGC_SERVO_TUNING
45908
+ get_and_reset_uoh_alloc_info();
45908
45909
uint64_t suspended_end_ts = GetHighPrecisionTimeStamp();
45909
45910
last_bgc_info[last_bgc_info_index].pause_durations[1] = (size_t)(suspended_end_ts - suspended_start_time);
45910
45911
total_suspended_time += last_bgc_info[last_bgc_info_index].pause_durations[1];
@@ -46233,6 +46234,7 @@ void gc_heap::background_sweep()
46233
46234
concurrent_print_time_delta ("Swe SOH");
46234
46235
FIRE_EVENT(BGC1stSweepEnd, 0);
46235
46236
46237
+ //block concurrent allocation for UOH objects
46236
46238
enter_spin_lock (&more_space_lock_uoh);
46237
46239
add_saved_spinlock_info (true, me_acquire, mt_bgc_uoh_sweep, msl_entered);
46238
46240
@@ -46288,6 +46290,15 @@ void gc_heap::background_sweep()
46288
46290
// be accurate.
46289
46291
compute_new_dynamic_data (max_generation);
46290
46292
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
+
46291
46302
#ifdef DOUBLY_LINKED_FL
46292
46303
current_bgc_state = bgc_not_in_process;
46293
46304
@@ -50257,17 +50268,15 @@ void gc_heap::check_and_adjust_bgc_tuning (int gen_number, size_t physical_size,
50257
50268
}
50258
50269
}
50259
50270
}
50271
+ #endif //BGC_SERVO_TUNING
50260
50272
50261
- void gc_heap::get_and_reset_loh_alloc_info ()
50273
+ void gc_heap::get_and_reset_uoh_alloc_info ()
50262
50274
{
50263
- if (!bgc_tuning::enable_fl_tuning)
50264
- return;
50275
+ total_uoh_a_last_bgc = 0;
50265
50276
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;
50271
50280
#ifdef MULTIPLE_HEAPS
50272
50281
for (int i = 0; i < gc_heap::n_heaps; i++)
50273
50282
{
@@ -50276,21 +50285,32 @@ void gc_heap::get_and_reset_loh_alloc_info()
50276
50285
{
50277
50286
gc_heap* hp = pGenGCHeap;
50278
50287
#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
+ }
50285
50306
}
50286
50307
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 ));
50290
50311
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 ;
50292
50313
}
50293
- #endif //BGC_SERVO_TUNING
50294
50314
50295
50315
bool gc_heap::is_pm_ratio_exceeded()
50296
50316
{
0 commit comments