void testTimed() throws IOException, InterruptedException {
      long startRow = getStartRow();
      long lastRow = getLastRow();
      // Report on completion of 1/10th of total.
      for (int ii = 0; ii < opts.cycles; ii++) {
        if (opts.cycles > 1) LOG.info("Cycle=" + ii + " of " + opts.cycles);
        for (long i = startRow; i < lastRow; i++) {
          if (i % everyN != 0) continue;
          long startTime = System.nanoTime();
          boolean requestSent = false;
          Span span = TraceUtil.getGlobalTracer().spanBuilder("test row").startSpan();
          try (Scope scope = span.makeCurrent()) {
            requestSent = testRow(i, startTime);
          } finally {
            span.end();
          }
          if ((i - startRow) > opts.measureAfter) {
            // If multiget or multiput is enabled, say set to 10, testRow() returns immediately
            // first 9 times and sends the actual get request in the 10th iteration.
            // We should only set latency when actual request is sent because otherwise
            // it turns out to be 0.
            if (requestSent) {
              long latency = (System.nanoTime() - startTime) / 1000;
              latencyHistogram.update(latency);
              if ((opts.latencyThreshold > 0) && (latency / 1000 >= opts.latencyThreshold)) {
                numOfReplyOverLatencyThreshold++;
              }
            }
            if (status != null && i > 0 && (i % getReportingPeriod()) == 0) {
              status.setStatus(generateStatus(startRow, i, lastRow));
            }
          }
        }
      }
    }
Provides an extension point for tests that don't want a per row invocation.
hbase-diagnostics/src/main/java/org/apache/hadoop/hbase/PerformanceEvaluation.java