comparison src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @ 4709:fd2b426c30db

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
author johnc
date Wed, 14 Dec 2011 17:43:55 -0800
parents 3c648b9ad052
children 41406797186b
comparison
equal deleted inserted replaced
4708:3c648b9ad052 4709:fd2b426c30db
1840 _retained_old_gc_alloc_region(NULL), 1840 _retained_old_gc_alloc_region(NULL),
1841 _surviving_young_words(NULL), 1841 _surviving_young_words(NULL),
1842 _full_collections_completed(0), 1842 _full_collections_completed(0),
1843 _in_cset_fast_test(NULL), 1843 _in_cset_fast_test(NULL),
1844 _in_cset_fast_test_base(NULL), 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_time_stamp(NULL) {
1846 _g1h = this; // To catch bugs. 1848 _g1h = this; // To catch bugs.
1847 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) { 1849 if (_process_strong_tasks == NULL || !_process_strong_tasks->valid()) {
1848 vm_exit_during_initialization("Failed necessary allocation."); 1850 vm_exit_during_initialization("Failed necessary allocation.");
1849 } 1851 }
1850 1852
1861 for (int i = 0; i < n_queues; i++) { 1863 for (int i = 0; i < n_queues; i++) {
1862 iter_arr[i] = new HeapRegionRemSetIterator(); 1864 iter_arr[i] = new HeapRegionRemSetIterator();
1863 } 1865 }
1864 _rem_set_iterator = iter_arr; 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_time_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues);
1870
1866 for (int i = 0; i < n_queues; i++) { 1871 for (int i = 0; i < n_queues; i++) {
1867 RefToScanQueue* q = new RefToScanQueue(); 1872 RefToScanQueue* q = new RefToScanQueue();
1868 q->initialize(); 1873 q->initialize();
1869 _task_queues->register_queue(i, q); 1874 _task_queues->register_queue(i, q);
1870 } 1875 }
1876
1877 clear_cset_start_regions();
1871 1878
1872 guarantee(_task_queues != NULL, "task_queues allocation failure."); 1879 guarantee(_task_queues != NULL, "task_queues allocation failure.");
1873 } 1880 }
1874 1881
1875 jint G1CollectedHeap::initialize() { 1882 jint G1CollectedHeap::initialize() {
2685 collection_set_iterate(&cl); 2692 collection_set_iterate(&cl);
2686 return cl.failures() == 0; 2693 return cl.failures() == 0;
2687 } 2694 }
2688 #endif // ASSERT 2695 #endif // ASSERT
2689 2696
2690 // We want the parallel threads to start their collection 2697 // Clear the cached CSet starting regions and (more importantly)
2691 // set iteration at different collection set regions to 2698 // the time stamps. Called when we reset the GC time stamp.
2692 // avoid contention. 2699 void G1CollectedHeap::clear_cset_start_regions() {
2693 // If we have: 2700 assert(_worker_cset_start_region != NULL, "sanity");
2694 // n collection set regions 2701 assert(_worker_cset_start_region_time_stamp != NULL, "sanity");
2695 // p threads 2702
2696 // Then thread t will start at region t * floor (n/p) 2703 int n_queues = MAX2((int)ParallelGCThreads, 1);
2697 2704 for (int i = 0; i < n_queues; i++) {
2705 _worker_cset_start_region[i] = NULL;
2706 _worker_cset_start_region_time_stamp[i] = 0;
2707 }
2708 }
2709
2710 // Given the id of a worker, obtain or calculate a suitable
2711 // starting region for iterating over the current collection set.
2698 HeapRegion* G1CollectedHeap::start_cset_region_for_worker(int worker_i) { 2712 HeapRegion* G1CollectedHeap::start_cset_region_for_worker(int worker_i) {
2699 HeapRegion* result = g1_policy()->collection_set(); 2713 assert(get_gc_time_stamp() > 0, "should have been updated by now");
2714
2715 HeapRegion* result = NULL;
2716 unsigned gc_time_stamp = get_gc_time_stamp();
2717
2718 if (_worker_cset_start_region_time_stamp[worker_i] == gc_time_stamp) {
2719 // Cached starting region for current worker was set
2720 // during the current pause - so it's valid.
2721 // Note: the cached starting heap region may be NULL
2722 // (when the collection set is empty).
2723 result = _worker_cset_start_region[worker_i];
2724 assert(result == NULL || result->in_collection_set(), "sanity");
2725 return result;
2726 }
2727
2728 // The cached entry was not valid so let's calculate
2729 // a suitable starting heap region for this worker.
2730
2731 // We want the parallel threads to start their collection
2732 // set iteration at different collection set regions to
2733 // avoid contention.
2734 // If we have:
2735 // n collection set regions
2736 // p threads
2737 // Then thread t will start at region floor ((t * n) / p)
2738
2739 result = g1_policy()->collection_set();
2700 if (G1CollectedHeap::use_parallel_gc_threads()) { 2740 if (G1CollectedHeap::use_parallel_gc_threads()) {
2701 size_t cs_size = g1_policy()->cset_region_length(); 2741 size_t cs_size = g1_policy()->cset_region_length();
2702 int n_workers = workers()->total_workers(); 2742 int active_workers = workers()->active_workers();
2703 size_t cs_spans = cs_size / n_workers; 2743 assert(UseDynamicNumberOfGCThreads ||
2704 size_t ind = cs_spans * worker_i; 2744 active_workers == workers()->total_workers(),
2705 for (size_t i = 0; i < ind; i++) { 2745 "Unless dynamic should use total workers");
2746
2747 size_t end_ind = (cs_size * worker_i) / active_workers;
2748 size_t start_ind = 0;
2749
2750 if (worker_i > 0 &&
2751 _worker_cset_start_region_time_stamp[worker_i - 1] == gc_time_stamp) {
2752 // Previous workers starting region is valid
2753 // so let's iterate from there
2754 start_ind = (cs_size * (worker_i - 1)) / active_workers;
2755 result = _worker_cset_start_region[worker_i - 1];
2756 }
2757
2758 for (size_t i = start_ind; i < end_ind; i++) {
2706 result = result->next_in_collection_set(); 2759 result = result->next_in_collection_set();
2707 } 2760 }
2708 } 2761 }
2762
2763 // Note: the calculated starting heap region may be NULL
2764 // (when the collection set is empty).
2765 assert(result == NULL || result->in_collection_set(), "sanity");
2766 assert(_worker_cset_start_region_time_stamp[worker_i] != gc_time_stamp,
2767 "should be updated only once per pause");
2768 _worker_cset_start_region[worker_i] = result;
2769 OrderAccess::storestore();
2770 _worker_cset_start_region_time_stamp[worker_i] = gc_time_stamp;
2709 return result; 2771 return result;
2710 } 2772 }
2711 2773
2712 void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) { 2774 void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
2713 HeapRegion* r = g1_policy()->collection_set(); 2775 HeapRegion* r = g1_policy()->collection_set();