package fastPercentiles;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class PercentileRecorder {
    private int count;
    private int range;
    private int[] data;
    private final ReentrantLock dataLock = new ReentrantLock();

    public int getRange() {
        return range;
    }

    public int getCount() {
        return count;
    }

    public PercentileRecorder(int range) {
        this.range = range;
        this.data = new int[this.range];
        for (int i = 0; i < this.range; i++) {
            data[i] = 0;
        }
    }

    public void record(int value) {
        if (value > range) {
            throw new Error("Value" + value + " out of percentile ranges");
        }
        
        dataLock.lock();
        
        this.data[value]++;
        this.count++;
        
        dataLock.unlock();
    }

    public Percentile[] percentiles() throws Exception {
        dataLock.lock();

        Percentile[] results = new Percentile[100];
        int partitionSize = count > 100 ? count / 100 : 1;
        for (int i=0; i < 100; i++) {
            results[i] = new Percentile(partitionSize);
        }
        
        int percentileIdx = 0;
        Percentile curPercentile = results[percentileIdx];
        for (int value = 0; value < data.length; value++) {
            int valueCount = data[value];
            int qTaken = 0;
            int qLeft = valueCount;

            while (qLeft > 0) {
                qTaken = curPercentile.spaceLeft() >= qLeft ? qLeft : curPercentile.spaceLeft();
                qLeft -= qTaken;

                curPercentile.record(value, qTaken);

                if (curPercentile.isFull()) {
                    results[percentileIdx] = curPercentile;
                    
                    if (percentileIdx < 99 && qLeft > 0) {
                        percentileIdx++;                    
                        curPercentile = results[percentileIdx];
                    } else if (qLeft > 0) {
                        curPercentile.record(value, qLeft);
                        qLeft = 0;
                    }
                }
            }
        }

        dataLock.unlock();

        return results;
    }
}

@@ -160,26 +160,30 @@
 te int count
+ = 0
 ;%0A
-
     private 
@@ -217,16 +217,74 @@
 %5D data;%0A
+    private int minVal = -1;%0A    private int maxVal = -1;%0A
     priv
@@ -841,32 +841,161 @@
 ock();%0A        %0A
+        if (minVal == -1 %7C%7C value %3C minVal) minVal = value;%0A        if (maxVal == -1 %7C%7C value %3E maxVal) maxVal = value;%0A        %0A
         this.dat
@@ -1360,32 +1360,128 @@
 Size);%0A        %7D
+%0A%0A        if (count == 0) %7B%0A            dataLock.unlock();%0A            return results;%0A        %7D
 %0A        %0A      
@@ -1589,17 +1589,22 @@
 value = 
-0
+minVal
 ; value 
@@ -1609,19 +1609,14 @@
 e %3C 
-data.length
+maxVal
 ; va

Optimize performance in percentilerecorder based on value range