All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonarsource.performance.measure.MeasurementCost Maven / Gradle / Ivy

Go to download

Logic to capture a hierarchy of performance measures, save it into a file, and merge files

The newest version!
/*
 * SonarSource Performance Measure Library
 * Copyright (C) 2009-2024 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.sonarsource.performance.measure;

import javax.annotation.CheckForNull;

public class MeasurementCost {

  public static final String MEASUREMENT_COST_NAME = "#MeasurementCost_v1";
  public static final String SUBTRACTED_MEASUREMENT_COST_NAME = "#MeasurementCost_subtracted_v1";

  public final long createChild;
  public final long incrementChild;
  public final long nanoTime;
  public final long observationCost;

  public MeasurementCost(DurationMeasure measurementCost) {
    createChild = averageDuration(measurementCost, "createChild");
    incrementChild = averageDuration(measurementCost, "incrementChild");
    nanoTime = averageDuration(measurementCost, "nanoTime");
    observationCost = averageDuration(measurementCost, "observationCost");
  }

  @CheckForNull
  public static MeasurementCost observationCostOf(DurationMeasure measure) {
    DurationMeasure costMeasure = measure.get(MEASUREMENT_COST_NAME);
    if (costMeasure == null) {
      costMeasure = measure.get(SUBTRACTED_MEASUREMENT_COST_NAME);
    }
    return costMeasure != null ? new MeasurementCost(costMeasure) : null;
  }

  public static DurationMeasure subtractObservationCost(DurationMeasure measure) {
    DurationMeasure measureCopy = measure.copy();
    DurationMeasure measurementCostNode = measureCopy.remove(MEASUREMENT_COST_NAME);
    if (measurementCostNode != null) {
      MeasurementCost measurementCost = new MeasurementCost(measurementCostNode);
      measurementCost.recursiveSubtractObservationCost(measureCopy);
      measurementCostNode.rename(SUBTRACTED_MEASUREMENT_COST_NAME);
      measureCopy.addOrMerge(measurementCostNode);
    }
    return measureCopy;
  }

  static long averageDuration(DurationMeasure measurementCost, String name) {
    DurationMeasure measure = measurementCost.get(name);
    if (measure == null) {
      throw new IllegalStateException("Missing " + name);
    }
    return measure.calls() == 0 ? 0 : (measure.durationNanos() / measure.calls());
  }

  ChildCounter recursiveSubtractObservationCost(DurationMeasure measure) {
    ChildCounter childCounter = ChildCounter.ZERO;
    for (DurationMeasure child : measure.children()) {
      childCounter = childCounter.add(recursiveSubtractObservationCost(child));
    }
    long cost = observationCost * measure.calls() + childCounter.cost(this);
    measure.subtractDuration(Math.min(cost, measure.durationNanos()));
    return childCounter.add(ChildCounter.of(measure));
  }

  static class ChildCounter {

    static final ChildCounter ZERO = new ChildCounter(0, 0);

    long createChildCount;
    long incrementChildCount;

    public ChildCounter(long createChildCount, long incrementChildCount) {
      this.createChildCount = createChildCount;
      this.incrementChildCount = incrementChildCount;
    }

    static ChildCounter of(DurationMeasure measure) {
      long count = measure.calls();
      if (count == 0) {
        return ZERO;
      }
      return new ChildCounter(1, count - 1);
    }

    ChildCounter add(ChildCounter other) {
      return new ChildCounter(createChildCount + other.createChildCount, incrementChildCount + other.incrementChildCount);
    }

    long cost(MeasurementCost measurementCost) {
      return createChildCount * measurementCost.createChild + incrementChildCount * measurementCost.incrementChild;
    }

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy