/* * Copyright 2014 NAVER Corp. * * Licensed 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 com.navercorp.pinpoint.web.util; import com.navercorp.pinpoint.common.util.MathUtils; import com.navercorp.pinpoint.web.vo.Range; /** * @author hyungil.jeong */ public class TimeWindowSlotCentricSampler implements TimeWindowSampler { private static final long ONE_SECOND = 1000L; static final long DEFAULT_MINIMUM_TIMESLOT = 5 * ONE_SECOND; static final long DEFAULT_IDEAL_NUM_TIMESLOTS = 200; private final long minTimeslot; private final long idealNumTimeslots; public TimeWindowSlotCentricSampler() { this.minTimeslot = DEFAULT_MINIMUM_TIMESLOT; this.idealNumTimeslots = DEFAULT_IDEAL_NUM_TIMESLOTS; } public TimeWindowSlotCentricSampler(long minTimeslot, long idealNumTimeslots) { this.minTimeslot = minTimeslot; this.idealNumTimeslots = idealNumTimeslots; } /** * <p>This implementation returns the window size that would generate the number of timeslots closest to * <tt>idealNumTimeslots</tt> for a given <tt>range</tt>. * <p>Additionally, the window size is generated in multiples of * <tt>minTimeslot</tt>. * * @param range range to calculate the time window over * @return size of the ideal time window */ @Override public long getWindowSize(Range range) { final long periodMs = range.getRange(); final long idealTimeslotSize = periodMs / this.idealNumTimeslots; if (idealTimeslotSize < this.minTimeslot) { return this.minTimeslot; } if (idealTimeslotSize % this.minTimeslot == 0) { return idealTimeslotSize; } else { final long nearestMultipleOfMinTimeslotSize = MathUtils.roundToNearestMultipleOf(idealTimeslotSize, this.minTimeslot); return findOptimalWindowSize(periodMs, nearestMultipleOfMinTimeslotSize); } } private long findOptimalWindowSize(long periodMs, long nearestMultipleOfMinTimeslotSize) { final double idealTimeslotSize = (double)periodMs / this.idealNumTimeslots; final long timeslotSizeToCompare = nearestMultipleOfMinTimeslotSize < idealTimeslotSize ? nearestMultipleOfMinTimeslotSize + this.minTimeslot : nearestMultipleOfMinTimeslotSize - this.minTimeslot; if (Math.abs(nearestMultipleOfMinTimeslotSize - idealTimeslotSize) / ((double)nearestMultipleOfMinTimeslotSize / this.minTimeslot) < Math.abs(timeslotSizeToCompare - idealTimeslotSize) / ((double)timeslotSizeToCompare / this.minTimeslot)) { return nearestMultipleOfMinTimeslotSize; } else { return timeslotSizeToCompare; } } }