7119908: G1: Cache CSet start region for each worker for subsequent reuse

Wed, 14 Dec 2011 17:43:55 -0800

author
johnc
date
Wed, 14 Dec 2011 17:43:55 -0800
changeset 3336
fd2b426c30db
parent 3335
3c648b9ad052
child 3337
41406797186b

7119908: G1: Cache CSet start region for each worker for subsequent reuse
Summary: Cache workers' calculated starting heap region, used for parallel iteration over the collcection set, for subsequent reuse.
Reviewed-by: tonyp, brutisso

src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Dec 14 12:15:26 2011 +0100
     1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Dec 14 17:43:55 2011 -0800
     1.3 @@ -1842,7 +1842,9 @@
     1.4    _full_collections_completed(0),
     1.5    _in_cset_fast_test(NULL),
     1.6    _in_cset_fast_test_base(NULL),
     1.7 -  _dirty_cards_region_list(NULL) {
     1.8 +  _dirty_cards_region_list(NULL),
     1.9 +  _worker_cset_start_region(NULL),
    1.10 +  _worker_cset_start_region_time_stamp(NULL) {
    1.11    _g1h = this; // To catch bugs.
    1.12    if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) {
    1.13      vm_exit_during_initialization("Failed necessary allocation.");
    1.14 @@ -1863,12 +1865,17 @@
    1.15    }
    1.16    _rem_set_iterator = iter_arr;
    1.17  
    1.18 +  _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues);
    1.19 +  _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues);
    1.20 +
    1.21    for (int i = 0; i < n_queues; i++) {
    1.22      RefToScanQueue* q = new RefToScanQueue();
    1.23      q->initialize();
    1.24      _task_queues->register_queue(i, q);
    1.25    }
    1.26  
    1.27 +  clear_cset_start_regions();
    1.28 +
    1.29    guarantee(_task_queues != NULL, "task_queues allocation failure.");
    1.30  }
    1.31  
    1.32 @@ -2687,25 +2694,80 @@
    1.33  }
    1.34  #endif // ASSERT
    1.35  
    1.36 -// We want the parallel threads to start their collection
    1.37 -// set iteration at different collection set regions to
    1.38 -// avoid contention.
    1.39 -// If we have:
    1.40 -//          n collection set regions
    1.41 -//          p threads
    1.42 -// Then thread t will start at region t * floor (n/p)
    1.43 -
    1.44 +// Clear the cached CSet starting regions and (more importantly)
    1.45 +// the time stamps. Called when we reset the GC time stamp.
    1.46 +void G1CollectedHeap::clear_cset_start_regions() {
    1.47 +  assert(_worker_cset_start_region != NULL, "sanity");
    1.48 +  assert(_worker_cset_start_region_time_stamp != NULL, "sanity");
    1.49 +
    1.50 +  int n_queues = MAX2((int)ParallelGCThreads, 1);
    1.51 +  for (int i = 0; i < n_queues; i++) {
    1.52 +    _worker_cset_start_region[i] = NULL;
    1.53 +    _worker_cset_start_region_time_stamp[i] = 0;
    1.54 +  }
    1.55 +}
    1.56 +
    1.57 +// Given the id of a worker, obtain or calculate a suitable
    1.58 +// starting region for iterating over the current collection set.
    1.59  HeapRegion* G1CollectedHeap::start_cset_region_for_worker(int worker_i) {
    1.60 -  HeapRegion* result = g1_policy()->collection_set();
    1.61 +  assert(get_gc_time_stamp() > 0, "should have been updated by now");
    1.62 +
    1.63 +  HeapRegion* result = NULL;
    1.64 +  unsigned gc_time_stamp = get_gc_time_stamp();
    1.65 +
    1.66 +  if (_worker_cset_start_region_time_stamp[worker_i] == gc_time_stamp) {
    1.67 +    // Cached starting region for current worker was set
    1.68 +    // during the current pause - so it's valid.
    1.69 +    // Note: the cached starting heap region may be NULL
    1.70 +    // (when the collection set is empty).
    1.71 +    result = _worker_cset_start_region[worker_i];
    1.72 +    assert(result == NULL || result->in_collection_set(), "sanity");
    1.73 +    return result;
    1.74 +  }
    1.75 +
    1.76 +  // The cached entry was not valid so let's calculate
    1.77 +  // a suitable starting heap region for this worker.
    1.78 +
    1.79 +  // We want the parallel threads to start their collection
    1.80 +  // set iteration at different collection set regions to
    1.81 +  // avoid contention.
    1.82 +  // If we have:
    1.83 +  //          n collection set regions
    1.84 +  //          p threads
    1.85 +  // Then thread t will start at region floor ((t * n) / p)
    1.86 +
    1.87 +  result = g1_policy()->collection_set();
    1.88    if (G1CollectedHeap::use_parallel_gc_threads()) {
    1.89      size_t cs_size = g1_policy()->cset_region_length();
    1.90 -    int n_workers = workers()->total_workers();
    1.91 -    size_t cs_spans = cs_size / n_workers;
    1.92 -    size_t ind      = cs_spans * worker_i;
    1.93 -    for (size_t i = 0; i < ind; i++) {
    1.94 +    int active_workers = workers()->active_workers();
    1.95 +    assert(UseDynamicNumberOfGCThreads ||
    1.96 +             active_workers == workers()->total_workers(),
    1.97 +             "Unless dynamic should use total workers");
    1.98 +
    1.99 +    size_t end_ind   = (cs_size * worker_i) / active_workers;
   1.100 +    size_t start_ind = 0;
   1.101 +
   1.102 +    if (worker_i > 0 &&
   1.103 +        _worker_cset_start_region_time_stamp[worker_i - 1] == gc_time_stamp) {
   1.104 +      // Previous workers starting region is valid
   1.105 +      // so let's iterate from there
   1.106 +      start_ind = (cs_size * (worker_i - 1)) / active_workers;
   1.107 +      result = _worker_cset_start_region[worker_i - 1];
   1.108 +    }
   1.109 +
   1.110 +    for (size_t i = start_ind; i < end_ind; i++) {
   1.111        result = result->next_in_collection_set();
   1.112      }
   1.113    }
   1.114 +
   1.115 +  // Note: the calculated starting heap region may be NULL
   1.116 +  // (when the collection set is empty).
   1.117 +  assert(result == NULL || result->in_collection_set(), "sanity");
   1.118 +  assert(_worker_cset_start_region_time_stamp[worker_i] != gc_time_stamp,
   1.119 +         "should be updated only once per pause");
   1.120 +  _worker_cset_start_region[worker_i] = result;
   1.121 +  OrderAccess::storestore();
   1.122 +  _worker_cset_start_region_time_stamp[worker_i] = gc_time_stamp;
   1.123    return result;
   1.124  }
   1.125  
     2.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Dec 14 12:15:26 2011 +0100
     2.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Dec 14 17:43:55 2011 -0800
     2.3 @@ -943,6 +943,16 @@
     2.4    // discovery.
     2.5    G1CMIsAliveClosure _is_alive_closure_cm;
     2.6  
     2.7 +  // Cache used by G1CollectedHeap::start_cset_region_for_worker().
     2.8 +  HeapRegion** _worker_cset_start_region;
     2.9 +
    2.10 +  // Time stamp to validate the regions recorded in the cache
    2.11 +  // used by G1CollectedHeap::start_cset_region_for_worker().
    2.12 +  // The heap region entry for a given worker is valid iff
    2.13 +  // the associated time stamp value matches the current value
    2.14 +  // of G1CollectedHeap::_gc_time_stamp.
    2.15 +  unsigned int* _worker_cset_start_region_time_stamp;
    2.16 +
    2.17    enum G1H_process_strong_roots_tasks {
    2.18      G1H_PS_mark_stack_oops_do,
    2.19      G1H_PS_refProcessor_oops_do,
    2.20 @@ -1030,6 +1040,9 @@
    2.21    void reset_gc_time_stamp() {
    2.22      _gc_time_stamp = 0;
    2.23      OrderAccess::fence();
    2.24 +    // Clear the cached CSet starting regions and time stamps.
    2.25 +    // Their validity is dependent on the GC timestamp.
    2.26 +    clear_cset_start_regions();
    2.27    }
    2.28  
    2.29    void increment_gc_time_stamp() {
    2.30 @@ -1300,9 +1313,12 @@
    2.31    bool check_cset_heap_region_claim_values(jint claim_value);
    2.32  #endif // ASSERT
    2.33  
    2.34 -  // Given the id of a worker, calculate a suitable
    2.35 -  // starting region for iterating over the current
    2.36 -  // collection set.
    2.37 +  // Clear the cached cset start regions and (more importantly)
    2.38 +  // the time stamps. Called when we reset the GC time stamp.
    2.39 +  void clear_cset_start_regions();
    2.40 +
    2.41 +  // Given the id of a worker, obtain or calculate a suitable
    2.42 +  // starting region for iterating over the current collection set.
    2.43    HeapRegion* start_cset_region_for_worker(int worker_i);
    2.44  
    2.45    // Iterate over the regions (if any) in the current collection set.

mercurial