/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.cassandra.utils;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLongArray;
public class EstimatedHistogram
{
/**
* This series starts at 1 and grows by 1.2 each time (rounding down and removing duplicates). It goes from 1
* to around 30M, which will give us timing resolution from microseconds to 30 seconds, with less precision
* as the numbers get larger.
*/
private static final long[] bucketOffsets = {
1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 15, 18, 22, 26, 31, 38, 46, 55, 66, 79, 95, 114, 137, 164, 197, 237, 284, 341, 410, 492, 590,
708, 850, 1020, 1224, 1469, 1763, 2116, 2539, 3047, 3657, 4388, 5266, 6319, 7583, 9100, 10920, 13104, 15725, 18870, 22644,
27173, 32608, 39130, 46956, 56347, 67617, 81140, 97368, 116842, 140210, 168252, 201903, 242283, 290740, 348888, 418666,
502400, 602880, 723456, 868147, 1041776, 1250132, 1500158, 1800190, 2160228, 2592274, 3110728, 3732874, 4479449, 5375339,
6450407, 7740489, 9288586, 11146304, 13375565, 16050678, 19260813, 23112976, 27735572, 33282686
};
private static final int numBuckets = bucketOffsets.length + 1;
final AtomicLongArray buckets;
public EstimatedHistogram()
{
buckets = new AtomicLongArray(numBuckets);
}
public void add(long n)
{
int index = Arrays.binarySearch(bucketOffsets, n);
if (index < 0)
{
//inexact match, find closest bucket
index = -index - 1;
}
else
{
//exact match, so we want the next highest one
index += 1;
}
buckets.incrementAndGet(index);
}
public long[] get(Boolean reset)
{
long[] rv = new long[numBuckets];
for (int i = 0; i < numBuckets; i++)
rv[i] = buckets.get(i);
if (reset)
for (int i = 0; i < numBuckets; i++)
buckets.set(i, 0L);
return rv;
}
public static long[] getBucketOffsets()
{
return bucketOffsets;
}
}