|
@@ -5,6 +5,7 @@
|
|
|
*/
|
|
|
package org.elasticsearch.xpack.core.ml.inference.trainedmodel;
|
|
|
|
|
|
+import org.elasticsearch.Version;
|
|
|
import org.elasticsearch.common.Nullable;
|
|
|
import org.elasticsearch.common.ParseField;
|
|
|
import org.elasticsearch.common.io.stream.StreamInput;
|
|
@@ -20,15 +21,13 @@ import org.elasticsearch.xpack.core.ml.utils.ToXContentParams;
|
|
|
import java.io.IOException;
|
|
|
import java.time.Instant;
|
|
|
import java.util.Objects;
|
|
|
-import java.util.concurrent.atomic.LongAdder;
|
|
|
-import java.util.concurrent.locks.ReadWriteLock;
|
|
|
-import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
|
|
|
|
public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
|
|
|
public static final String NAME = "inference_stats";
|
|
|
public static final ParseField MISSING_ALL_FIELDS_COUNT = new ParseField("missing_all_fields_count");
|
|
|
public static final ParseField INFERENCE_COUNT = new ParseField("inference_count");
|
|
|
+ public static final ParseField CACHE_MISS_COUNT = new ParseField("cache_miss_count");
|
|
|
public static final ParseField MODEL_ID = new ParseField("model_id");
|
|
|
public static final ParseField NODE_ID = new ParseField("node_id");
|
|
|
public static final ParseField FAILURE_COUNT = new ParseField("failure_count");
|
|
@@ -38,12 +37,13 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
public static final ConstructingObjectParser<InferenceStats, Void> PARSER = new ConstructingObjectParser<>(
|
|
|
NAME,
|
|
|
true,
|
|
|
- a -> new InferenceStats((Long)a[0], (Long)a[1], (Long)a[2], (String)a[3], (String)a[4], (Instant)a[5])
|
|
|
+ a -> new InferenceStats((Long)a[0], (Long)a[1], (Long)a[2], (Long)a[3], (String)a[4], (String)a[5], (Instant)a[6])
|
|
|
);
|
|
|
static {
|
|
|
PARSER.declareLong(ConstructingObjectParser.constructorArg(), MISSING_ALL_FIELDS_COUNT);
|
|
|
PARSER.declareLong(ConstructingObjectParser.constructorArg(), INFERENCE_COUNT);
|
|
|
PARSER.declareLong(ConstructingObjectParser.constructorArg(), FAILURE_COUNT);
|
|
|
+ PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), CACHE_MISS_COUNT);
|
|
|
PARSER.declareString(ConstructingObjectParser.constructorArg(), MODEL_ID);
|
|
|
PARSER.declareString(ConstructingObjectParser.constructorArg(), NODE_ID);
|
|
|
PARSER.declareField(ConstructingObjectParser.constructorArg(),
|
|
@@ -51,9 +51,6 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
TIMESTAMP,
|
|
|
ObjectParser.ValueType.VALUE);
|
|
|
}
|
|
|
- public static InferenceStats emptyStats(String modelId, String nodeId) {
|
|
|
- return new InferenceStats(0L, 0L, 0L, modelId, nodeId, Instant.now());
|
|
|
- }
|
|
|
|
|
|
public static String docId(String modelId, String nodeId) {
|
|
|
return NAME + "-" + modelId + "-" + nodeId;
|
|
@@ -62,6 +59,7 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
private final long missingAllFieldsCount;
|
|
|
private final long inferenceCount;
|
|
|
private final long failureCount;
|
|
|
+ private final long cacheMissCount;
|
|
|
private final String modelId;
|
|
|
private final String nodeId;
|
|
|
private final Instant timeStamp;
|
|
@@ -69,12 +67,14 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
private InferenceStats(Long missingAllFieldsCount,
|
|
|
Long inferenceCount,
|
|
|
Long failureCount,
|
|
|
+ Long cacheMissCount,
|
|
|
String modelId,
|
|
|
String nodeId,
|
|
|
Instant instant) {
|
|
|
- this(unbox(missingAllFieldsCount),
|
|
|
- unbox(inferenceCount),
|
|
|
- unbox(failureCount),
|
|
|
+ this(unboxOrZero(missingAllFieldsCount),
|
|
|
+ unboxOrZero(inferenceCount),
|
|
|
+ unboxOrZero(failureCount),
|
|
|
+ unboxOrZero(cacheMissCount),
|
|
|
modelId,
|
|
|
nodeId,
|
|
|
instant);
|
|
@@ -83,12 +83,14 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
public InferenceStats(long missingAllFieldsCount,
|
|
|
long inferenceCount,
|
|
|
long failureCount,
|
|
|
+ long cacheMissCount,
|
|
|
String modelId,
|
|
|
String nodeId,
|
|
|
Instant timeStamp) {
|
|
|
this.missingAllFieldsCount = missingAllFieldsCount;
|
|
|
this.inferenceCount = inferenceCount;
|
|
|
this.failureCount = failureCount;
|
|
|
+ this.cacheMissCount = cacheMissCount;
|
|
|
this.modelId = modelId;
|
|
|
this.nodeId = nodeId;
|
|
|
this.timeStamp = timeStamp == null ?
|
|
@@ -100,6 +102,11 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
this.missingAllFieldsCount = in.readVLong();
|
|
|
this.inferenceCount = in.readVLong();
|
|
|
this.failureCount = in.readVLong();
|
|
|
+ if (in.getVersion().onOrAfter(Version.V_7_9_0)) {
|
|
|
+ this.cacheMissCount = in.readVLong();
|
|
|
+ } else {
|
|
|
+ this.cacheMissCount = 0L;
|
|
|
+ }
|
|
|
this.modelId = in.readOptionalString();
|
|
|
this.nodeId = in.readOptionalString();
|
|
|
this.timeStamp = in.readInstant();
|
|
@@ -117,6 +124,10 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
return failureCount;
|
|
|
}
|
|
|
|
|
|
+ public long getCacheMissCount() {
|
|
|
+ return cacheMissCount;
|
|
|
+ }
|
|
|
+
|
|
|
public String getModelId() {
|
|
|
return modelId;
|
|
|
}
|
|
@@ -130,7 +141,7 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
}
|
|
|
|
|
|
public boolean hasStats() {
|
|
|
- return missingAllFieldsCount > 0 || inferenceCount > 0 || failureCount > 0;
|
|
|
+ return missingAllFieldsCount > 0 || inferenceCount > 0 || failureCount > 0 || cacheMissCount > 0;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -145,6 +156,7 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
}
|
|
|
builder.field(FAILURE_COUNT.getPreferredName(), failureCount);
|
|
|
builder.field(INFERENCE_COUNT.getPreferredName(), inferenceCount);
|
|
|
+ builder.field(CACHE_MISS_COUNT.getPreferredName(), cacheMissCount);
|
|
|
builder.field(MISSING_ALL_FIELDS_COUNT.getPreferredName(), missingAllFieldsCount);
|
|
|
builder.timeField(TIMESTAMP.getPreferredName(), TIMESTAMP.getPreferredName() + "_string", timeStamp.toEpochMilli());
|
|
|
builder.endObject();
|
|
@@ -159,6 +171,7 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
return missingAllFieldsCount == that.missingAllFieldsCount
|
|
|
&& inferenceCount == that.inferenceCount
|
|
|
&& failureCount == that.failureCount
|
|
|
+ && cacheMissCount == that.cacheMissCount
|
|
|
&& Objects.equals(modelId, that.modelId)
|
|
|
&& Objects.equals(nodeId, that.nodeId)
|
|
|
&& Objects.equals(timeStamp, that.timeStamp);
|
|
@@ -166,7 +179,7 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
|
|
|
@Override
|
|
|
public int hashCode() {
|
|
|
- return Objects.hash(missingAllFieldsCount, inferenceCount, failureCount, modelId, nodeId, timeStamp);
|
|
|
+ return Objects.hash(missingAllFieldsCount, inferenceCount, failureCount, cacheMissCount, modelId, nodeId, timeStamp);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -175,13 +188,14 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
"missingAllFieldsCount=" + missingAllFieldsCount +
|
|
|
", inferenceCount=" + inferenceCount +
|
|
|
", failureCount=" + failureCount +
|
|
|
+ ", cacheMissCount=" + cacheMissCount +
|
|
|
", modelId='" + modelId + '\'' +
|
|
|
", nodeId='" + nodeId + '\'' +
|
|
|
", timeStamp=" + timeStamp +
|
|
|
'}';
|
|
|
}
|
|
|
|
|
|
- private static long unbox(@Nullable Long value) {
|
|
|
+ private static long unboxOrZero(@Nullable Long value) {
|
|
|
return value == null ? 0L : value;
|
|
|
}
|
|
|
|
|
@@ -194,6 +208,9 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
out.writeVLong(this.missingAllFieldsCount);
|
|
|
out.writeVLong(this.inferenceCount);
|
|
|
out.writeVLong(this.failureCount);
|
|
|
+ if (out.getVersion().onOrAfter(Version.V_7_9_0)) {
|
|
|
+ out.writeVLong(this.cacheMissCount);
|
|
|
+ }
|
|
|
out.writeOptionalString(this.modelId);
|
|
|
out.writeOptionalString(this.nodeId);
|
|
|
out.writeInstant(timeStamp);
|
|
@@ -201,66 +218,55 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
|
|
|
public static class Accumulator {
|
|
|
|
|
|
- private final LongAdder missingFieldsAccumulator = new LongAdder();
|
|
|
- private final LongAdder inferenceAccumulator = new LongAdder();
|
|
|
- private final LongAdder failureCountAccumulator = new LongAdder();
|
|
|
+ private long missingFieldsAccumulator = 0L;
|
|
|
+ private long inferenceAccumulator = 0L;
|
|
|
+ private long failureCountAccumulator = 0L;
|
|
|
+ private long cacheMissAccumulator = 0L;
|
|
|
private final String modelId;
|
|
|
private final String nodeId;
|
|
|
- // curious reader
|
|
|
- // you may be wondering why the lock set to the fair.
|
|
|
- // When `currentStatsAndReset` is called, we want it guaranteed that it will eventually execute.
|
|
|
- // If a ReadWriteLock is unfair, there are no such guarantees.
|
|
|
- // A call for the `writelock::lock` could pause indefinitely.
|
|
|
- private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
|
|
|
-
|
|
|
- public Accumulator(String modelId, String nodeId) {
|
|
|
+
|
|
|
+ public Accumulator(String modelId, String nodeId, long cacheMisses) {
|
|
|
this.modelId = modelId;
|
|
|
this.nodeId = nodeId;
|
|
|
+ this.cacheMissAccumulator = cacheMisses;
|
|
|
}
|
|
|
|
|
|
- public Accumulator(InferenceStats previousStats) {
|
|
|
+ Accumulator(InferenceStats previousStats) {
|
|
|
this.modelId = previousStats.modelId;
|
|
|
this.nodeId = previousStats.nodeId;
|
|
|
- this.missingFieldsAccumulator.add(previousStats.missingAllFieldsCount);
|
|
|
- this.inferenceAccumulator.add(previousStats.inferenceCount);
|
|
|
- this.failureCountAccumulator.add(previousStats.failureCount);
|
|
|
+ this.missingFieldsAccumulator += previousStats.missingAllFieldsCount;
|
|
|
+ this.inferenceAccumulator += previousStats.inferenceCount;
|
|
|
+ this.failureCountAccumulator += previousStats.failureCount;
|
|
|
+ this.cacheMissAccumulator += previousStats.cacheMissCount;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * NOT Thread Safe
|
|
|
+ *
|
|
|
+ * @param otherStats the other stats with which to increment the current stats
|
|
|
+ * @return Updated accumulator
|
|
|
+ */
|
|
|
public Accumulator merge(InferenceStats otherStats) {
|
|
|
- this.missingFieldsAccumulator.add(otherStats.missingAllFieldsCount);
|
|
|
- this.inferenceAccumulator.add(otherStats.inferenceCount);
|
|
|
- this.failureCountAccumulator.add(otherStats.failureCount);
|
|
|
+ this.missingFieldsAccumulator += otherStats.missingAllFieldsCount;
|
|
|
+ this.inferenceAccumulator += otherStats.inferenceCount;
|
|
|
+ this.failureCountAccumulator += otherStats.failureCount;
|
|
|
+ this.cacheMissAccumulator += otherStats.cacheMissCount;
|
|
|
return this;
|
|
|
}
|
|
|
|
|
|
- public Accumulator incMissingFields() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- this.missingFieldsAccumulator.increment();
|
|
|
- return this;
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
+ public synchronized Accumulator incMissingFields() {
|
|
|
+ this.missingFieldsAccumulator++;
|
|
|
+ return this;
|
|
|
}
|
|
|
|
|
|
- public Accumulator incInference() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- this.inferenceAccumulator.increment();
|
|
|
- return this;
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
+ public synchronized Accumulator incInference() {
|
|
|
+ this.inferenceAccumulator++;
|
|
|
+ return this;
|
|
|
}
|
|
|
|
|
|
- public Accumulator incFailure() {
|
|
|
- readWriteLock.readLock().lock();
|
|
|
- try {
|
|
|
- this.failureCountAccumulator.increment();
|
|
|
- return this;
|
|
|
- } finally {
|
|
|
- readWriteLock.readLock().unlock();
|
|
|
- }
|
|
|
+ public synchronized Accumulator incFailure() {
|
|
|
+ this.failureCountAccumulator++;
|
|
|
+ return this;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -269,23 +275,20 @@ public class InferenceStats implements ToXContentObject, Writeable {
|
|
|
* Returns the current stats and resets the values of all the counters.
|
|
|
* @return The current stats
|
|
|
*/
|
|
|
- public InferenceStats currentStatsAndReset() {
|
|
|
- readWriteLock.writeLock().lock();
|
|
|
- try {
|
|
|
- InferenceStats stats = currentStats(Instant.now());
|
|
|
- this.missingFieldsAccumulator.reset();
|
|
|
- this.inferenceAccumulator.reset();
|
|
|
- this.failureCountAccumulator.reset();
|
|
|
- return stats;
|
|
|
- } finally {
|
|
|
- readWriteLock.writeLock().unlock();
|
|
|
- }
|
|
|
+ public synchronized InferenceStats currentStatsAndReset() {
|
|
|
+ InferenceStats stats = currentStats(Instant.now());
|
|
|
+ this.missingFieldsAccumulator = 0L;
|
|
|
+ this.inferenceAccumulator = 0L;
|
|
|
+ this.failureCountAccumulator = 0L;
|
|
|
+ this.cacheMissAccumulator = 0L;
|
|
|
+ return stats;
|
|
|
}
|
|
|
|
|
|
public InferenceStats currentStats(Instant timeStamp) {
|
|
|
- return new InferenceStats(missingFieldsAccumulator.longValue(),
|
|
|
- inferenceAccumulator.longValue(),
|
|
|
- failureCountAccumulator.longValue(),
|
|
|
+ return new InferenceStats(missingFieldsAccumulator,
|
|
|
+ inferenceAccumulator,
|
|
|
+ failureCountAccumulator,
|
|
|
+ cacheMissAccumulator,
|
|
|
modelId,
|
|
|
nodeId,
|
|
|
timeStamp);
|