| /** |
| * 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.hadoop.metrics2.util; |
| |
| import static org.junit.Assert.*; |
| |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.Map; |
| import java.util.Random; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| public class TestSampleQuantiles { |
| |
| static final Quantile[] quantiles = { new Quantile(0.50, 0.050), |
| new Quantile(0.75, 0.025), new Quantile(0.90, 0.010), |
| new Quantile(0.95, 0.005), new Quantile(0.99, 0.001) }; |
| |
| SampleQuantiles estimator; |
| |
| @Before |
| public void init() { |
| estimator = new SampleQuantiles(quantiles); |
| } |
| |
| /** |
| * Check that the counts of the number of items in the window and sample are |
| * incremented correctly as items are added. |
| */ |
| @Test |
| public void testCount() throws IOException { |
| // Counts start off zero |
| assertEquals(estimator.getCount(), 0); |
| assertEquals(estimator.getSampleCount(), 0); |
| |
| // Snapshot should be null if there are no entries. |
| assertNull(estimator.snapshot()); |
| |
| // Count increment correctly by 1 |
| estimator.insert(1337); |
| assertEquals(estimator.getCount(), 1); |
| estimator.snapshot(); |
| assertEquals(estimator.getSampleCount(), 1); |
| |
| assertEquals( |
| "50.00 %ile +/- 5.00%: 1337\n" + |
| "75.00 %ile +/- 2.50%: 1337\n" + |
| "90.00 %ile +/- 1.00%: 1337\n" + |
| "95.00 %ile +/- 0.50%: 1337\n" + |
| "99.00 %ile +/- 0.10%: 1337", estimator.toString()); |
| } |
| |
| /** |
| * Check that counts and quantile estimates are correctly reset after a call |
| * to {@link SampleQuantiles#clear()}. |
| */ |
| @Test |
| public void testClear() throws IOException { |
| for (int i = 0; i < 1000; i++) { |
| estimator.insert(i); |
| } |
| estimator.clear(); |
| assertEquals(estimator.getCount(), 0); |
| assertEquals(estimator.getSampleCount(), 0); |
| assertNull(estimator.snapshot()); |
| } |
| |
| /** |
| * Correctness test that checks that absolute error of the estimate is within |
| * specified error bounds for some randomly permuted streams of items. |
| */ |
| @Test |
| public void testQuantileError() throws IOException { |
| final int count = 100000; |
| Random r = new Random(0xDEADDEAD); |
| Long[] values = new Long[count]; |
| for (int i = 0; i < count; i++) { |
| values[i] = (long) (i + 1); |
| } |
| // Do 10 shuffle/insert/check cycles |
| for (int i = 0; i < 10; i++) { |
| System.out.println("Starting run " + i); |
| Collections.shuffle(Arrays.asList(values), r); |
| estimator.clear(); |
| for (int j = 0; j < count; j++) { |
| estimator.insert(values[j]); |
| } |
| Map<Quantile, Long> snapshot; |
| snapshot = estimator.snapshot(); |
| for (Quantile q : quantiles) { |
| long actual = (long) (q.quantile * count); |
| long error = (long) (q.error * count); |
| long estimate = snapshot.get(q); |
| System.out |
| .println(String.format("Expected %d with error %d, estimated %d", |
| actual, error, estimate)); |
| assertTrue(estimate <= actual + error); |
| assertTrue(estimate >= actual - error); |
| } |
| } |
| } |
| } |