Thu, 20 Nov 2008 16:56:09 -0800
6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa
1 /*
2 * Copyright 2001-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
25 # include "incls/_precompiled.incl"
26 # include "incls/_numberSeq.cpp.incl"
28 AbsSeq::AbsSeq(double alpha) :
29 _num(0), _sum(0.0), _sum_of_squares(0.0),
30 _davg(0.0), _dvariance(0.0), _alpha(alpha) {
31 }
33 void AbsSeq::add(double val) {
34 if (_num == 0) {
35 // if the sequence is empty, the davg is the same as the value
36 _davg = val;
37 // and the variance is 0
38 _dvariance = 0.0;
39 } else {
40 // otherwise, calculate both
41 _davg = (1.0 - _alpha) * val + _alpha * _davg;
42 double diff = val - _davg;
43 _dvariance = (1.0 - _alpha) * diff * diff + _alpha * _dvariance;
44 }
45 }
47 double AbsSeq::avg() const {
48 if (_num == 0)
49 return 0.0;
50 else
51 return _sum / total();
52 }
54 double AbsSeq::variance() const {
55 if (_num <= 1)
56 return 0.0;
58 double x_bar = avg();
59 double result = _sum_of_squares / total() - x_bar * x_bar;
60 if (result < 0.0) {
61 // due to loss-of-precision errors, the variance might be negative
62 // by a small bit
64 // guarantee(-0.1 < result && result < 0.0,
65 // "if variance is negative, it should be very small");
66 result = 0.0;
67 }
68 return result;
69 }
71 double AbsSeq::sd() const {
72 double var = variance();
73 guarantee( var >= 0.0, "variance should not be negative" );
74 return sqrt(var);
75 }
77 double AbsSeq::davg() const {
78 return _davg;
79 }
81 double AbsSeq::dvariance() const {
82 if (_num <= 1)
83 return 0.0;
85 double result = _dvariance;
86 if (result < 0.0) {
87 // due to loss-of-precision errors, the variance might be negative
88 // by a small bit
90 guarantee(-0.1 < result && result < 0.0,
91 "if variance is negative, it should be very small");
92 result = 0.0;
93 }
94 return result;
95 }
97 double AbsSeq::dsd() const {
98 double var = dvariance();
99 guarantee( var >= 0.0, "variance should not be negative" );
100 return sqrt(var);
101 }
103 NumberSeq::NumberSeq(double alpha) :
104 AbsSeq(alpha), _maximum(0.0), _last(0.0) {
105 }
107 bool NumberSeq::check_nums(NumberSeq *total, int n, NumberSeq **parts) {
108 for (int i = 0; i < n; ++i) {
109 if (parts[i] != NULL && total->num() != parts[i]->num())
110 return false;
111 }
112 return true;
113 }
115 NumberSeq::NumberSeq(NumberSeq *total, int n, NumberSeq **parts) {
116 guarantee(check_nums(total, n, parts), "all seq lengths should match");
117 double sum = total->sum();
118 for (int i = 0; i < n; ++i) {
119 if (parts[i] != NULL)
120 sum -= parts[i]->sum();
121 }
123 _num = total->num();
124 _sum = sum;
126 // we do not calculate these...
127 _sum_of_squares = -1.0;
128 _maximum = -1.0;
129 _davg = -1.0;
130 _dvariance = -1.0;
131 }
133 void NumberSeq::add(double val) {
134 AbsSeq::add(val);
136 _last = val;
137 if (_num == 0) {
138 _maximum = val;
139 } else {
140 if (val > _maximum)
141 _maximum = val;
142 }
143 _sum += val;
144 _sum_of_squares += val * val;
145 ++_num;
146 }
149 TruncatedSeq::TruncatedSeq(int length, double alpha):
150 AbsSeq(alpha), _length(length), _next(0) {
151 _sequence = NEW_C_HEAP_ARRAY(double, _length);
152 for (int i = 0; i < _length; ++i)
153 _sequence[i] = 0.0;
154 }
156 void TruncatedSeq::add(double val) {
157 AbsSeq::add(val);
159 // get the oldest value in the sequence...
160 double old_val = _sequence[_next];
161 // ...remove it from the sum and sum of squares
162 _sum -= old_val;
163 _sum_of_squares -= old_val * old_val;
165 // ...and update them with the new value
166 _sum += val;
167 _sum_of_squares += val * val;
169 // now replace the old value with the new one
170 _sequence[_next] = val;
171 _next = (_next + 1) % _length;
173 // only increase it if the buffer is not full
174 if (_num < _length)
175 ++_num;
177 guarantee( variance() > -1.0, "variance should be >= 0" );
178 }
180 // can't easily keep track of this incrementally...
181 double TruncatedSeq::maximum() const {
182 if (_num == 0)
183 return 0.0;
184 double ret = _sequence[0];
185 for (int i = 1; i < _num; ++i) {
186 double val = _sequence[i];
187 if (val > ret)
188 ret = val;
189 }
190 return ret;
191 }
193 double TruncatedSeq::last() const {
194 if (_num == 0)
195 return 0.0;
196 unsigned last_index = (_next + _length - 1) % _length;
197 return _sequence[last_index];
198 }
200 double TruncatedSeq::oldest() const {
201 if (_num == 0)
202 return 0.0;
203 else if (_num < _length)
204 // index 0 always oldest value until the array is full
205 return _sequence[0];
206 else {
207 // since the array is full, _next is over the oldest value
208 return _sequence[_next];
209 }
210 }
212 double TruncatedSeq::predict_next() const {
213 if (_num == 0)
214 return 0.0;
216 double num = (double) _num;
217 double x_squared_sum = 0.0;
218 double x_sum = 0.0;
219 double y_sum = 0.0;
220 double xy_sum = 0.0;
221 double x_avg = 0.0;
222 double y_avg = 0.0;
224 int first = (_next + _length - _num) % _length;
225 for (int i = 0; i < _num; ++i) {
226 double x = (double) i;
227 double y = _sequence[(first + i) % _length];
229 x_squared_sum += x * x;
230 x_sum += x;
231 y_sum += y;
232 xy_sum += x * y;
233 }
234 x_avg = x_sum / num;
235 y_avg = y_sum / num;
237 double Sxx = x_squared_sum - x_sum * x_sum / num;
238 double Sxy = xy_sum - x_sum * y_sum / num;
239 double b1 = Sxy / Sxx;
240 double b0 = y_avg - b1 * x_avg;
242 return b0 + b1 * num;
243 }