Mercurial > hg > truffle
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(); |