Print this page
rev 2869 : 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:

Split Close
Expand all
Collapse all
          --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
          +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
↓ open down ↓ 1834 lines elided ↑ open up ↑
1835 1835    _old_set("Old Set"),
1836 1836    _humongous_set("Master Humongous Set"),
1837 1837    _free_regions_coming(false),
1838 1838    _young_list(new YoungList(this)),
1839 1839    _gc_time_stamp(0),
1840 1840    _retained_old_gc_alloc_region(NULL),
1841 1841    _surviving_young_words(NULL),
1842 1842    _full_collections_completed(0),
1843 1843    _in_cset_fast_test(NULL),
1844 1844    _in_cset_fast_test_base(NULL),
1845      -  _dirty_cards_region_list(NULL) {
     1845 +  _dirty_cards_region_list(NULL),
     1846 +  _worker_cset_start_region(NULL),
     1847 +  _worker_cset_start_region_stamp(NULL) {
1846 1848    _g1h = this; // To catch bugs.
1847 1849    if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) {
1848 1850      vm_exit_during_initialization("Failed necessary allocation.");
1849 1851    }
1850 1852  
1851 1853    _humongous_object_threshold_in_words = HeapRegion::GrainWords / 2;
1852 1854  
1853 1855    int n_queues = MAX2((int)ParallelGCThreads, 1);
1854 1856    _task_queues = new RefToScanQueueSet(n_queues);
1855 1857  
1856 1858    int n_rem_sets = HeapRegionRemSet::num_par_rem_sets();
1857 1859    assert(n_rem_sets > 0, "Invariant.");
1858 1860  
1859 1861    HeapRegionRemSetIterator** iter_arr =
1860 1862      NEW_C_HEAP_ARRAY(HeapRegionRemSetIterator*, n_queues);
1861 1863    for (int i = 0; i < n_queues; i++) {
1862 1864      iter_arr[i] = new HeapRegionRemSetIterator();
1863 1865    }
1864 1866    _rem_set_iterator = iter_arr;
1865 1867  
     1868 +  _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues);
     1869 +  _worker_cset_start_region_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues);
     1870 +
1866 1871    for (int i = 0; i < n_queues; i++) {
1867 1872      RefToScanQueue* q = new RefToScanQueue();
1868 1873      q->initialize();
1869 1874      _task_queues->register_queue(i, q);
     1875 +    
     1876 +    _worker_cset_start_region[i] = NULL;
     1877 +    _worker_cset_start_region_stamp[i] = 0;
1870 1878    }
1871 1879  
1872 1880    guarantee(_task_queues != NULL, "task_queues allocation failure.");
1873 1881  }
1874 1882  
1875 1883  jint G1CollectedHeap::initialize() {
1876 1884    CollectedHeap::pre_initialize();
1877 1885    os::enable_vtime();
1878 1886  
1879 1887    // Necessary to satisfy locking discipline assertions.
↓ open down ↓ 797 lines elided ↑ open up ↑
2677 2685    }
2678 2686  };
2679 2687  
2680 2688  bool G1CollectedHeap::check_cset_heap_region_claim_values(jint claim_value) {
2681 2689    CheckClaimValuesInCSetHRClosure cl(claim_value);
2682 2690    collection_set_iterate(&cl);
2683 2691    return cl.failures() == 0;
2684 2692  }
2685 2693  #endif // ASSERT
2686 2694  
2687      -// We want the parallel threads to start their collection
2688      -// set iteration at different collection set regions to
2689      -// avoid contention.
2690      -// If we have:
2691      -//          n collection set regions
2692      -//          p threads
2693      -// Then thread t will start at region t * floor (n/p)
2694      -
     2695 +// Given the id of a worker, obtain or calculate a suitable
     2696 +// starting region for iterating over the current collection set.
2695 2697  HeapRegion* G1CollectedHeap::start_cset_region_for_worker(int worker_i) {
2696      -  HeapRegion* result = g1_policy()->collection_set();
     2698 +  assert(_worker_cset_start_region != NULL, "sanity");
     2699 +  assert(_worker_cset_start_region_stamp != NULL, "sanity");
     2700 +  assert(total_collections() > 0, "should have been updated by now");
     2701 +
     2702 +  HeapRegion* result = NULL;
     2703 +
     2704 +  if (_worker_cset_start_region_stamp[worker_i] == total_collections()) {
     2705 +    // Cached starting region for current worker was set
     2706 +    // during the current pause - so it's valid.
     2707 +    // Note: the cached starting heap region may be NULL
     2708 +    // (when the collection set is empty).
     2709 +    result = _worker_cset_start_region[worker_i];
     2710 +    assert(result == NULL || result->in_collection_set(), "sanity");
     2711 +    return result;
     2712 +  }
     2713 +
     2714 +  // The cached entry was not valid so let's calculate
     2715 +  // a suitable starting heap region for this worker.
     2716 +
     2717 +  // We want the parallel threads to start their collection
     2718 +  // set iteration at different collection set regions to
     2719 +  // avoid contention.
     2720 +  // If we have:
     2721 +  //          n collection set regions
     2722 +  //          p threads
     2723 +  // Then thread t will start at region t * floor (n/p)
     2724 +
     2725 +  result = g1_policy()->collection_set();
2697 2726    if (G1CollectedHeap::use_parallel_gc_threads()) {
2698 2727      size_t cs_size = g1_policy()->cset_region_length();
2699 2728      int n_workers = workers()->total_workers();
2700 2729      size_t cs_spans = cs_size / n_workers;
2701 2730      size_t ind      = cs_spans * worker_i;
2702 2731      for (size_t i = 0; i < ind; i++) {
2703 2732        result = result->next_in_collection_set();
2704 2733      }
2705 2734    }
     2735 +
     2736 +  // Note: the calculated starting heap region may be NULL
     2737 +  // (when the collection set is empty).
     2738 +  assert(result == NULL || result->in_collection_set(), "sanity");
     2739 +  assert(_worker_cset_start_region_stamp[worker_i] != total_collections(),
     2740 +         "should be updated only once per pause");
     2741 +  _worker_cset_start_region[worker_i] = result;
     2742 +  _worker_cset_start_region_stamp[worker_i] = total_collections();
2706 2743    return result;
2707 2744  }
2708 2745  
2709 2746  void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
2710 2747    HeapRegion* r = g1_policy()->collection_set();
2711 2748    while (r != NULL) {
2712 2749      HeapRegion* next = r->next_in_collection_set();
2713 2750      if (cl->doHeapRegion(r)) {
2714 2751        cl->incomplete();
2715 2752        return;
↓ open down ↓ 809 lines elided ↑ open up ↑
3525 3562                           /* silent      */ false,
3526 3563                           /* option      */ VerifyOption_G1UsePrevMarking);
3527 3564  
3528 3565        }
3529 3566  
3530 3567        COMPILER2_PRESENT(DerivedPointerTable::clear());
3531 3568  
3532 3569        // Please see comment in g1CollectedHeap.hpp and
3533 3570        // G1CollectedHeap::ref_processing_init() to see how
3534 3571        // reference processing currently works in G1.
3535      -
     3572 +      
3536 3573        // Enable discovery in the STW reference processor
3537 3574        ref_processor_stw()->enable_discovery(true /*verify_disabled*/,
3538 3575                                              true /*verify_no_refs*/);
3539 3576  
3540 3577        {
3541 3578          // We want to temporarily turn off discovery by the
3542 3579          // CM ref processor, if necessary, and turn it back on
3543 3580          // on again later if we do. Using a scoped
3544 3581          // NoRefDiscovery object will do this.
3545 3582          NoRefDiscovery no_cm_discovery(ref_processor_cm());
↓ open down ↓ 1696 lines elided ↑ open up ↑
5242 5279    //
5243 5280    // We also need to do this copying before we process the reference
5244 5281    // objects discovered by the STW ref processor in case one of these
5245 5282    // referents points to another object which is also referenced by an
5246 5283    // object discovered by the STW ref processor.
5247 5284  
5248 5285    int active_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
5249 5286                          workers()->active_workers() : 1);
5250 5287  
5251 5288    assert(active_workers == workers()->active_workers(),
5252      -         "Need to reset active_workers");
     5289 +         "Need to reset active_workers");  
5253 5290    set_par_threads(active_workers);
5254 5291    G1ParPreserveCMReferentsTask keep_cm_referents(this, active_workers, _task_queues);
5255 5292  
5256 5293    if (G1CollectedHeap::use_parallel_gc_threads()) {
5257 5294      workers()->run_task(&keep_cm_referents);
5258 5295    } else {
5259 5296      keep_cm_referents.work(0);
5260 5297    }
5261 5298  
5262 5299    set_par_threads(0);
↓ open down ↓ 988 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX