content: /*
   * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
   * (the "License"). You may not use this work except in compliance with the License, which is
   * available at www.apache.org/licenses/LICENSE-2.0
   *
   * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
   * either express or implied, as more fully set forth in the License.
   *
   * See the NOTICE file distributed with this work for information regarding copyright ownership.
   */
  
  package alluxio.stress.common;
  
  import alluxio.Constants;
  import alluxio.annotation.SuppressFBWarnings;
  import alluxio.stress.StressConstants;
  import alluxio.stress.TaskResult;
  
  import org.HdrHistogram.Histogram;
  
  import java.nio.ByteBuffer;
  import java.util.Arrays;
  import java.util.zip.DataFormatException;
  
  /**
   * abstract class that calculate statistics for{@link TaskResult}.
   */
  public class TaskResultStatistics {
    public long mNumSuccesses;
    @SuppressFBWarnings(value = "EI_EXPOSE_REP2")
    public byte[] mResponseTimeNsRaw;
    @SuppressFBWarnings(value = "EI_EXPOSE_REP2")
    public long[] mMaxResponseTimeNs;
  
    protected TaskResultStatistics() {
      // Default constructor required for json deserialization
    }
  
    /**
     * Merges (updates) a task result statistics with this statistics.
     *
     * @param statistics the task result statistics to merge
     */
    public void merge(TaskResultStatistics statistics) throws Exception {
      mNumSuccesses += statistics.mNumSuccesses;
  
      Histogram responseTime =
          new Histogram(StressConstants.TIME_HISTOGRAM_MAX, StressConstants.TIME_HISTOGRAM_PRECISION);
      if (mResponseTimeNsRaw != null) {
        responseTime.add(Histogram.decodeFromCompressedByteBuffer(ByteBuffer.wrap(mResponseTimeNsRaw),
            StressConstants.TIME_HISTOGRAM_MAX));
      }
      if (statistics.mResponseTimeNsRaw != null) {
        responseTime.add(Histogram.decodeFromCompressedByteBuffer(
            ByteBuffer.wrap(statistics.mResponseTimeNsRaw), StressConstants.TIME_HISTOGRAM_MAX));
      }
      encodeResponseTimeNsRaw(responseTime);
      for (int i = 0; i < mMaxResponseTimeNs.length; i++) {
        if (statistics.mMaxResponseTimeNs[i] > mMaxResponseTimeNs[i]) {
          mMaxResponseTimeNs[i] = statistics.mMaxResponseTimeNs[i];
        }
      }
    }
  
    /**
     * Encodes the histogram into the internal byte array.
     *
     * @param responseTimeNs the histogram (in ns)
     */
    public void encodeResponseTimeNsRaw(Histogram responseTimeNs) {
      ByteBuffer bb = ByteBuffer.allocate(responseTimeNs.getEstimatedFootprintInBytes());
      responseTimeNs.encodeIntoCompressedByteBuffer(bb,
          StressConstants.TIME_HISTOGRAM_COMPRESSION_LEVEL);
      bb.flip();
      mResponseTimeNsRaw = new byte[bb.limit()];
      bb.get(mResponseTimeNsRaw);
    }
  
    /**
     * Converts this class to {@link SummaryStatistics}.
     *
     * @return new SummaryStatistics
     * @throws DataFormatException if histogram decoding from compressed byte buffer fails
     */
    public SummaryStatistics toBenchSummaryStatistics() throws DataFormatException {
      Histogram responseTime =
          new Histogram(StressConstants.TIME_HISTOGRAM_MAX, StressConstants.TIME_HISTOGRAM_PRECISION);
      if (mResponseTimeNsRaw != null) {
        responseTime.add(Histogram.decodeFromCompressedByteBuffer(ByteBuffer.wrap(mResponseTimeNsRaw),
            StressConstants.TIME_HISTOGRAM_MAX));
      }
      float[] responseTimePercentile = new float[101];
      for (int i = 0; i <= 100; i++) {
        responseTimePercentile[i] = (float) responseTime.getValueAtPercentile(i) / Constants.MS_NANO;
      }
  
      float[] responseTime99Percentile = new float[StressConstants.TIME_99_COUNT];
      for (int i = 0; i < responseTime99Percentile.length; i++) {
        responseTime99Percentile[i] =
            (float) responseTime.getValueAtPercentile(100.0 - 1.0 / (Math.pow(10.0, i)))
                / Constants.MS_NANO;
      }
  
      float[] maxResponseTimesMs = new float[mMaxResponseTimeNs.length];
      Arrays.fill(maxResponseTimesMs, -1);
      for (int i = 0; i < mMaxResponseTimeNs.length; i++) {
        maxResponseTimesMs[i] = (float) mMaxResponseTimeNs[i] / Constants.MS_NANO;
      }
  
      return new SummaryStatistics(mNumSuccesses, responseTimePercentile, responseTime99Percentile,
          maxResponseTimesMs);
    }
  }
  