
org.robolectric.util.PerfStatsCollector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils Show documentation
Show all versions of utils Show documentation
An alternative Android testing framework.
The newest version!
package org.robolectric.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.robolectric.pluginapi.perf.Metadata;
import org.robolectric.pluginapi.perf.Metric;
import org.robolectric.pluginapi.perf.PerfStatsReporter;
/**
* Collects performance statistics for later reporting via {@link PerfStatsReporter}.
*
* @since 3.6
*/
public class PerfStatsCollector {
private static final PerfStatsCollector INSTANCE = new PerfStatsCollector();
private final Clock clock;
private final Map, Object> metadata = new HashMap<>();
private final Map metricMap = new HashMap<>();
private boolean enabled = true;
public PerfStatsCollector() {
this(System::nanoTime);
}
PerfStatsCollector(Clock clock) {
this.clock = clock;
}
public static PerfStatsCollector getInstance() {
return INSTANCE;
}
/** If not enabled, don't bother retaining perf stats, saving some memory and CPU cycles. */
public void setEnabled(boolean isEnabled) {
this.enabled = isEnabled;
}
public Event startEvent(String eventName) {
return new Event(eventName);
}
public T measure(String eventName, ThrowingSupplier supplier)
throws E {
boolean success = true;
Event event = startEvent(eventName);
try {
return supplier.get();
} catch (Exception e) {
success = false;
throw e;
} finally {
event.finished(success);
}
}
public void incrementCount(String eventName) {
synchronized (PerfStatsCollector.this) {
MetricKey key = new MetricKey(eventName, true);
Metric metric = metricMap.get(key);
if (metric == null) {
metricMap.put(key, metric = new Metric(key.name, key.success));
}
metric.incrementCount();
}
}
/** Supplier that throws an exception. */
// @FunctionalInterface -- not available on Android yet...
public interface ThrowingSupplier {
T get() throws F;
}
public void measure(String eventName, ThrowingRunnable runnable)
throws E {
boolean success = true;
Event event = startEvent(eventName);
try {
runnable.run();
} catch (Exception e) {
success = false;
throw e;
} finally {
event.finished(success);
}
}
/** Runnable that throws an exception. */
// @FunctionalInterface -- not available on Android yet...
public interface ThrowingRunnable {
void run() throws F;
}
public synchronized Collection getMetrics() {
return new ArrayList<>(metricMap.values());
}
public synchronized void putMetadata(Class metadataClass, T metadata) {
if (!enabled) {
return;
}
this.metadata.put(metadataClass, metadata);
}
public synchronized Metadata getMetadata() {
return new Metadata(metadata);
}
public void reset() {
metadata.clear();
metricMap.clear();
}
/** Event for perf stats collection. */
public class Event {
private final String name;
private final long startTimeNs;
Event(String name) {
this.name = name;
this.startTimeNs = clock.nanoTime();
}
public void finished() {
finished(true);
}
public void finished(boolean success) {
if (!enabled) {
return;
}
synchronized (PerfStatsCollector.this) {
MetricKey key = new MetricKey(name, success);
Metric metric = metricMap.get(key);
if (metric == null) {
metricMap.put(key, metric = new Metric(key.name, key.success));
}
metric.record(clock.nanoTime() - startTimeNs);
}
}
}
/** Metric key for perf stats collection. */
private static class MetricKey {
private final String name;
private final boolean success;
MetricKey(String name, boolean success) {
this.name = name;
this.success = success;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof MetricKey)) {
return false;
}
MetricKey metricKey = (MetricKey) o;
if (success != metricKey.success) {
return false;
}
return name != null ? name.equals(metricKey.name) : metricKey.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + (success ? 1 : 0);
return result;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy