/* * Copyright (c) 2018, Red Hat, Inc. All rights reserved. * * 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] = NULL; } } HdrSeq::~HdrSeq() { for (int c = 0; c < MagBuckets; c++) { int* sub = _hdr[c]; if (sub != NULL) { 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 == NULL) { 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] != NULL) { 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); for (int c = 0; c < BitsPerSize_t; c++) { _mags[c] = 0; } _sum = 0; } BinaryMagnitudeSeq::~BinaryMagnitudeSeq() { FREE_C_HEAP_ARRAY(size_t, _mags); } void BinaryMagnitudeSeq::add(size_t val) { Atomic::add(val, &_sum); int mag = log2_intptr(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((size_t)1, &_mags[mag]); } 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; }