| /* |
| * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| * |
| */ |
| |
| #include "precompiled.hpp" |
| |
| #include "gc/shenandoah/shenandoahNumberSeq.hpp" |
| #include "runtime/atomic.hpp" |
| |
| HdrSeq::HdrSeq() { |
| _hdr = NEW_C_HEAP_ARRAY(int*, MagBuckets, mtInternal); |
| for (int c = 0; c < MagBuckets; c++) { |
| _hdr[c] = nullptr; |
| } |
| } |
| |
| HdrSeq::~HdrSeq() { |
| for (int c = 0; c < MagBuckets; c++) { |
| int* sub = _hdr[c]; |
| if (sub != nullptr) { |
| FREE_C_HEAP_ARRAY(int, sub); |
| } |
| } |
| FREE_C_HEAP_ARRAY(int*, _hdr); |
| } |
| |
| void HdrSeq::add(double val) { |
| if (val < 0) { |
| assert (false, "value (%8.2f) is not negative", val); |
| val = 0; |
| } |
| |
| NumberSeq::add(val); |
| |
| double v = val; |
| int mag; |
| if (v > 0) { |
| mag = 0; |
| while (v >= 1) { |
| mag++; |
| v /= 10; |
| } |
| while (v < 0.1) { |
| mag--; |
| v *= 10; |
| } |
| } else { |
| mag = MagMinimum; |
| } |
| |
| int bucket = -MagMinimum + mag; |
| int sub_bucket = (int) (v * ValBuckets); |
| |
| // Defensively saturate for product bits |
| if (bucket < 0) { |
| assert (false, "bucket index (%d) underflow for value (%8.2f)", bucket, val); |
| bucket = 0; |
| } |
| |
| if (bucket >= MagBuckets) { |
| assert (false, "bucket index (%d) overflow for value (%8.2f)", bucket, val); |
| bucket = MagBuckets - 1; |
| } |
| |
| if (sub_bucket < 0) { |
| assert (false, "sub-bucket index (%d) underflow for value (%8.2f)", sub_bucket, val); |
| sub_bucket = 0; |
| } |
| |
| if (sub_bucket >= ValBuckets) { |
| assert (false, "sub-bucket index (%d) overflow for value (%8.2f)", sub_bucket, val); |
| sub_bucket = ValBuckets - 1; |
| } |
| |
| int* b = _hdr[bucket]; |
| if (b == nullptr) { |
| b = NEW_C_HEAP_ARRAY(int, ValBuckets, mtInternal); |
| for (int c = 0; c < ValBuckets; c++) { |
| b[c] = 0; |
| } |
| _hdr[bucket] = b; |
| } |
| b[sub_bucket]++; |
| } |
| |
| double HdrSeq::percentile(double level) const { |
| // target should be non-zero to find the first sample |
| int target = MAX2(1, (int) (level * num() / 100)); |
| int cnt = 0; |
| for (int mag = 0; mag < MagBuckets; mag++) { |
| if (_hdr[mag] != nullptr) { |
| for (int val = 0; val < ValBuckets; val++) { |
| cnt += _hdr[mag][val]; |
| if (cnt >= target) { |
| return pow(10.0, MagMinimum + mag) * val / ValBuckets; |
| } |
| } |
| } |
| } |
| return maximum(); |
| } |
| |
| BinaryMagnitudeSeq::BinaryMagnitudeSeq() { |
| _mags = NEW_C_HEAP_ARRAY(size_t, BitsPerSize_t, mtInternal); |
| clear(); |
| } |
| |
| BinaryMagnitudeSeq::~BinaryMagnitudeSeq() { |
| FREE_C_HEAP_ARRAY(size_t, _mags); |
| } |
| |
| void BinaryMagnitudeSeq::clear() { |
| for (int c = 0; c < BitsPerSize_t; c++) { |
| _mags[c] = 0; |
| } |
| _sum = 0; |
| } |
| |
| void BinaryMagnitudeSeq::add(size_t val) { |
| Atomic::add(&_sum, val); |
| |
| int mag = log2i_graceful(val) + 1; |
| |
| // Defensively saturate for product bits: |
| if (mag < 0) { |
| assert (false, "bucket index (%d) underflow for value (" SIZE_FORMAT ")", mag, val); |
| mag = 0; |
| } |
| |
| if (mag >= BitsPerSize_t) { |
| assert (false, "bucket index (%d) overflow for value (" SIZE_FORMAT ")", mag, val); |
| mag = BitsPerSize_t - 1; |
| } |
| |
| Atomic::add(&_mags[mag], (size_t)1); |
| } |
| |
| size_t BinaryMagnitudeSeq::level(int level) const { |
| if (0 <= level && level < BitsPerSize_t) { |
| return _mags[level]; |
| } else { |
| return 0; |
| } |
| } |
| |
| size_t BinaryMagnitudeSeq::num() const { |
| size_t r = 0; |
| for (int c = 0; c < BitsPerSize_t; c++) { |
| r += _mags[c]; |
| } |
| return r; |
| } |
| |
| size_t BinaryMagnitudeSeq::sum() const { |
| return _sum; |
| } |
| |
| int BinaryMagnitudeSeq::min_level() const { |
| for (int c = 0; c < BitsPerSize_t; c++) { |
| if (_mags[c] != 0) { |
| return c; |
| } |
| } |
| return BitsPerSize_t - 1; |
| } |
| |
| int BinaryMagnitudeSeq::max_level() const { |
| for (int c = BitsPerSize_t - 1; c > 0; c--) { |
| if (_mags[c] != 0) { |
| return c; |
| } |
| } |
| return 0; |
| } |