public void maybeThrottle(double observed) throws InterruptedException {
    synchronized (lock) {
      observedSoFar += observed;
      long now = time.nanoseconds();
      long elapsedNs = now - periodStartNs;

      // if we have completed an interval AND we have observed something, maybe
      // we should take a little nap
      if ((checkIntervalMs < 0 || elapsedNs > checkIntervalMs * Time.NsPerMs) && observedSoFar > 0) {
        double rateInSecs = elapsedNs > 0 ? (observedSoFar * Time.NsPerSec) / elapsedNs : Double.MAX_VALUE;
        if (throttleDown == rateInSecs > desiredRatePerSec) {
          // solve for the amount of time to sleep to make us hit the desired rate
          double desiredRateMs = desiredRatePerSec / Time.MsPerSec;
          double elapsedMs = elapsedNs / Time.NsPerMs;
          long sleepTime = Math.round(observedSoFar / desiredRateMs - elapsedMs);
          if (sleepTime > 0) {
            logger.trace("Natural rate is {} per second but desired rate is {}, sleeping for {} ms to compensate.",
                rateInSecs, desiredRatePerSec, sleepTime);
            synchronized (waitGuard) {
              if (enabled) {
                time.wait(waitGuard, sleepTime);
              }
            }
          }
        }
        periodStartNs = time.nanoseconds();
        observedSoFar = 0;
      }
    }
  }
Throttle if required
@param observed the newly observed units since the last time this method was called.
ambry-utils/src/main/java/com/github/ambry/utils/Throttler.java