1 | /* |
2 | * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | * |
5 | * This code is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 only, as |
7 | * published by the Free Software Foundation. |
8 | * |
9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
12 | * version 2 for more details (a copy is included in the LICENSE file that |
13 | * accompanied this code). |
14 | * |
15 | * You should have received a copy of the GNU General Public License version |
16 | * 2 along with this work; if not, write to the Free Software Foundation, |
17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
18 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_GC_SHARED_WORKERDATAARRAY_INLINE_HPP |
26 | #define SHARE_GC_SHARED_WORKERDATAARRAY_INLINE_HPP |
27 | |
28 | #include "gc/shared/workerDataArray.hpp" |
29 | #include "memory/allocation.inline.hpp" |
30 | #include "utilities/ostream.hpp" |
31 | |
32 | template <typename T> |
33 | WorkerDataArray<T>::WorkerDataArray(uint length, const char* title) : |
34 | _data(NULL), |
35 | _length(length), |
36 | _title(title) { |
37 | assert(length > 0, "Must have some workers to store data for" ); |
38 | _data = NEW_C_HEAP_ARRAY(T, _length, mtGC); |
39 | for (uint i = 0; i < MaxThreadWorkItems; i++) { |
40 | _thread_work_items[i] = NULL; |
41 | } |
42 | reset(); |
43 | } |
44 | |
45 | template <typename T> |
46 | void WorkerDataArray<T>::set(uint worker_i, T value) { |
47 | assert(worker_i < _length, "Worker %d is greater than max: %d" , worker_i, _length); |
48 | assert(_data[worker_i] == uninitialized(), "Overwriting data for worker %d in %s" , worker_i, _title); |
49 | _data[worker_i] = value; |
50 | } |
51 | |
52 | template <typename T> |
53 | T WorkerDataArray<T>::get(uint worker_i) const { |
54 | assert(worker_i < _length, "Worker %d is greater than max: %d" , worker_i, _length); |
55 | return _data[worker_i]; |
56 | } |
57 | |
58 | template <typename T> |
59 | WorkerDataArray<T>::~WorkerDataArray() { |
60 | FREE_C_HEAP_ARRAY(T, _data); |
61 | } |
62 | |
63 | template <typename T> |
64 | void WorkerDataArray<T>::link_thread_work_items(WorkerDataArray<size_t>* thread_work_items, uint index) { |
65 | assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)" , index, MaxThreadWorkItems); |
66 | _thread_work_items[index] = thread_work_items; |
67 | } |
68 | |
69 | template <typename T> |
70 | void WorkerDataArray<T>::set_thread_work_item(uint worker_i, size_t value, uint index) { |
71 | assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)" , index, MaxThreadWorkItems); |
72 | assert(_thread_work_items[index] != NULL, "No sub count" ); |
73 | _thread_work_items[index]->set(worker_i, value); |
74 | } |
75 | |
76 | template <typename T> |
77 | void WorkerDataArray<T>::add_thread_work_item(uint worker_i, size_t value, uint index) { |
78 | assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)" , index, MaxThreadWorkItems); |
79 | assert(_thread_work_items[index] != NULL, "No sub count" ); |
80 | _thread_work_items[index]->add(worker_i, value); |
81 | } |
82 | |
83 | template <typename T> |
84 | void WorkerDataArray<T>::set_or_add_thread_work_item(uint worker_i, size_t value, uint index) { |
85 | assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)" , index, MaxThreadWorkItems); |
86 | assert(_thread_work_items[index] != NULL, "No sub count" ); |
87 | if (_thread_work_items[index]->get(worker_i) == _thread_work_items[index]->uninitialized()) { |
88 | _thread_work_items[index]->set(worker_i, value); |
89 | } else { |
90 | _thread_work_items[index]->add(worker_i, value); |
91 | } |
92 | } |
93 | |
94 | template <typename T> |
95 | size_t WorkerDataArray<T>::get_thread_work_item(uint worker_i, uint index) { |
96 | assert(index < MaxThreadWorkItems, "Tried to access thread work item %u (max %u)" , index, MaxThreadWorkItems); |
97 | assert(_thread_work_items[index] != NULL, "No sub count" ); |
98 | return _thread_work_items[index]->get(worker_i); |
99 | } |
100 | |
101 | template <typename T> |
102 | void WorkerDataArray<T>::add(uint worker_i, T value) { |
103 | assert(worker_i < _length, "Worker %d is greater than max: %d" , worker_i, _length); |
104 | assert(_data[worker_i] != uninitialized(), "No data to add to for worker %d" , worker_i); |
105 | _data[worker_i] += value; |
106 | } |
107 | |
108 | template <typename T> |
109 | double WorkerDataArray<T>::average() const { |
110 | uint contributing_threads = 0; |
111 | for (uint i = 0; i < _length; ++i) { |
112 | if (get(i) != uninitialized()) { |
113 | contributing_threads++; |
114 | } |
115 | } |
116 | if (contributing_threads == 0) { |
117 | return 0.0; |
118 | } |
119 | return sum() / (double) contributing_threads; |
120 | } |
121 | |
122 | template <typename T> |
123 | T WorkerDataArray<T>::sum() const { |
124 | T s = 0; |
125 | for (uint i = 0; i < _length; ++i) { |
126 | if (get(i) != uninitialized()) { |
127 | s += get(i); |
128 | } |
129 | } |
130 | return s; |
131 | } |
132 | |
133 | template <typename T> |
134 | void WorkerDataArray<T>::set_all(T value) { |
135 | for (uint i = 0; i < _length; i++) { |
136 | _data[i] = value; |
137 | } |
138 | } |
139 | |
140 | template <class T> |
141 | void WorkerDataArray<T>::print_summary_on(outputStream* out, bool print_sum) const { |
142 | out->print("%-25s" , title()); |
143 | uint start = 0; |
144 | while (start < _length && get(start) == uninitialized()) { |
145 | start++; |
146 | } |
147 | if (start < _length) { |
148 | T min = get(start); |
149 | T max = min; |
150 | T sum = 0; |
151 | uint contributing_threads = 0; |
152 | for (uint i = start; i < _length; ++i) { |
153 | T value = get(i); |
154 | if (value != uninitialized()) { |
155 | max = MAX2(max, value); |
156 | min = MIN2(min, value); |
157 | sum += value; |
158 | contributing_threads++; |
159 | } |
160 | } |
161 | T diff = max - min; |
162 | assert(contributing_threads != 0, "Must be since we found a used value for the start index" ); |
163 | double avg = sum / (double) contributing_threads; |
164 | WDAPrinter::summary(out, min, avg, max, diff, sum, print_sum); |
165 | out->print_cr(", Workers: %d" , contributing_threads); |
166 | } else { |
167 | // No data for this phase. |
168 | out->print_cr(" skipped" ); |
169 | } |
170 | } |
171 | |
172 | template <class T> |
173 | void WorkerDataArray<T>::print_details_on(outputStream* out) const { |
174 | WDAPrinter::details(this, out); |
175 | } |
176 | |
177 | template <typename T> |
178 | void WorkerDataArray<T>::reset() { |
179 | set_all(uninitialized()); |
180 | for (uint i = 0; i < MaxThreadWorkItems; i++) { |
181 | if (_thread_work_items[i] != NULL) { |
182 | _thread_work_items[i]->reset(); |
183 | } |
184 | } |
185 | } |
186 | |
187 | #endif // SHARE_GC_SHARED_WORKERDATAARRAY_INLINE_HPP |
188 | |