core: perfmark API changes

This commit is contained in:
Carl Mastrangelo 2019-05-02 15:36:48 -07:00 committed by GitHub
parent 6807f39155
commit 54a9a15ac4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 95 additions and 176 deletions

View File

@ -69,7 +69,6 @@ java_library(
[
"src/main/java/io/grpc/perfmark/*.java",
],
exclude = ["src/main/java/io/grpc/perfmark/package-info.java"],
),
visibility = ["//:__subpackages__"],
deps = [

View File

@ -96,7 +96,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
boolean retryEnabled) {
this.method = method;
// TODO(carl-mastrangelo): consider moving this construction to ManagedChannelImpl.
this.tag = PerfTag.create(PerfTag.allocateNumericId(), method.getFullMethodName());
this.tag = PerfMark.createTag(method.getFullMethodName());
// If we know that the executor is a direct executor, we don't need to wrap it with a
// SerializingExecutor. This is purely for performance reasons.
// See https://github.com/grpc/grpc-java/issues/368
@ -187,7 +187,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
try {
startInternal(observer, headers);
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ClientCall.start");
}
}
@ -389,7 +389,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
try {
cancelInternal(message, cause);
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ClientCall.cancel");
}
}
@ -428,7 +428,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
try {
halfCloseInternal();
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ClientCall.halfClose");
}
}
@ -446,7 +446,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
try {
sendMessageInternal(message);
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ClientCall.sendMessage");
}
}
@ -534,7 +534,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
stream.cancel(status);
close(status, new Metadata());
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ClientCall.headersRead");
}
}
}
@ -574,7 +574,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
stream.cancel(status);
close(status, new Metadata());
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ClientCall.messagesAvailable");
}
}
}
@ -631,7 +631,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
try {
close(savedStatus, savedTrailers);
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ClientCall.closed");
}
}
}
@ -657,7 +657,7 @@ final class ClientCallImpl<ReqT, RespT> extends ClientCall<ReqT, RespT> {
stream.cancel(status);
close(status, new Metadata());
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ClientCall.onReady");
}
}
}

View File

@ -75,7 +75,7 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
this.stream = stream;
this.method = method;
// TODO(carl-mastrangelo): consider moving this to the ServerImpl to record startCall.
this.tag = PerfTag.create(PerfTag.allocateNumericId(), method.getFullMethodName());
this.tag = PerfMark.createTag(method.getFullMethodName());
this.context = context;
this.messageAcceptEncoding = inboundHeaders.get(MESSAGE_ACCEPT_ENCODING_KEY);
this.decompressorRegistry = decompressorRegistry;
@ -95,7 +95,7 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
try {
sendHeadersInternal(headers);
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ServerCall.sendHeaders");
}
}
@ -144,7 +144,7 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
try {
sendMessageInternal(message);
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ServerCall.sendMessage");
}
}
@ -197,7 +197,7 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
try {
closeInternal(status, trailers);
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(tag, "ServerCall.close");
}
}
@ -306,7 +306,7 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
Throwables.throwIfUnchecked(t);
throw new RuntimeException(t);
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(call.tag, "ServerCall.messagesAvailable");
}
}
@ -321,7 +321,7 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
try {
listener.onHalfClose();
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(call.tag, "ServerCall.halfClosed");
}
}
@ -343,7 +343,7 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
}
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(call.tag, "ServerCall.closed");
}
}
@ -356,7 +356,7 @@ final class ServerCallImpl<ReqT, RespT> extends ServerCall<ReqT, RespT> {
try {
listener.onReady();
} finally {
PerfMark.taskEnd();
PerfMark.taskEnd(call.tag, "ServerCall.closed");
}
}
}

View File

@ -17,13 +17,12 @@
package io.grpc.perfmark;
import com.google.errorprone.annotations.CompileTimeConstant;
import javax.annotation.concurrent.ThreadSafe;
import io.grpc.perfmark.PerfTag.TagFactory;
/**
* PerfMark is a collection of stub methods for marking key points in the RPC lifecycle. This
* class is {@link io.grpc.Internal} and {@link io.grpc.ExperimentalApi}. Do not use this yet.
*/
@ThreadSafe
public final class PerfMark {
private PerfMark() {
throw new AssertionError("nope");
@ -52,43 +51,26 @@ public final class PerfMark {
public static void taskStart(@CompileTimeConstant String taskName) {}
/**
* Start a Task with a Tag to identify it and with a time threshold; a task represents some work
* that spans some time, and you are interested in both its start time and end time.
* End a Task with a Tag to identify it; a task represents some work that spans some time, and
* you are interested in both its start time and end time.
*
* <p>Sometimes, you may be interested in only events that take more than a certain time
* threshold. In such cases, you can use this method. A Task that takes less than the specified
* threshold, along with all its sub-tasks, events, and additional tags will be discarded.
*
* @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't
* use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task
* does not have a numeric tag associated. In this case, you are encouraged to use {@link
* #taskStartWithMinPeriod(long, String)} or {@link PerfTag#create(String)}.
* @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will
* be discarded, along with its sub-tasks, events, and additional tags.
* @param tag a Tag object associated with the task start. This should be the tag used for the
* corresponding {@link #taskStart(PerfTag, String)} call.
* @param taskName The name of the task. <b>This parameter must be a compile-time constant!</b>
* Otherwise, instrumentation result will show "(invalid name)" for this task.
* Otherwise, instrumentation result will show "(invalid name)" for this task. This should
* be the name used by the corresponding {@link #taskStart(PerfTag, String)} call.
*/
public static void taskStartWithMinPeriod(
PerfTag tag, long minPeriodNanos, @CompileTimeConstant String taskName) {}
public static void taskEnd(PerfTag tag, @CompileTimeConstant String taskName) {}
/**
* Start a Task with time threshold. A task represents some work that spans some time, and you are
* interested in both its start time and end time.
* End a Task with a Tag to identify it; a task represents some work that spans some time, and
* you are interested in both its start time and end time.
*
* <p>Sometimes, you may be interested in only events that take more than a certain time
* threshold. In such cases, you can use this method. A task that takes less than the specified
* threshold, along with all its sub-tasks, events, and additional tags will be discarded.
*
* @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will
* be discarded, along with its sub-tasks, events, and additional tags.
* @param taskName The name of the task. <b>This parameter must be a compile-time constant!</b>
* Otherwise, instrumentation result will show "(invalid name)" for this task.
* Otherwise, instrumentation result will show "(invalid name)" for this task. This should
* be the name used by the corresponding {@link #taskStart(String)} call.
*/
public static void taskStartWithMinPeriod(
long minPeriodNanos, @CompileTimeConstant String taskName) {}
/** End a Task. See {@link #taskStart(PerfTag, String)}. */
public static void taskEnd() {}
public static void taskEnd(@CompileTimeConstant String taskName) {}
/**
* Start a Task with a Tag to identify it in a try-with-resource statement; a task represents some
@ -104,7 +86,7 @@ public final class PerfMark {
* Otherwise, instrumentation result will show "(invalid name)" for this task.
*/
public static PerfMarkTask task(PerfTag tag, @CompileTimeConstant String taskName) {
return AUTO_DO_NOTHING;
return NoopTask.INSTANCE;
}
/**
@ -117,59 +99,9 @@ public final class PerfMark {
* Otherwise, instrumentation result will show "(invalid name)" for this task.
*/
public static PerfMarkTask task(@CompileTimeConstant String taskName) {
return AUTO_DO_NOTHING;
return NoopTask.INSTANCE;
}
/**
* Start a Task with a Tag to identify it, and with time threshold, in a try-with-resource
* statement; a task represents some work that spans some time, and you are interested in both its
* start time and end time.
*
* <p>Use this in a try-with-resource statement so that task will end automatically.
*
* <p>Sometimes, you may be interested in only events that take more than a certain time
* threshold. In such cases, you can use this method. A task that takes less than the specified
* threshold, along with all its sub-tasks, events, and additional tags will be discarded.
*
* @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't
* use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task
* does not have a numeric tag associated. In this case, you are encouraged to use {@link
* #taskWithMinPeriod(long, String)} or {@link PerfTag#create(String)}.
* @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will
* be discarded, along with its sub-tasks, events, and additional tags.
* @param taskName The name of the task. <b>This parameter must be a compile-time constant!</b>
* Otherwise, instrumentation result will show "(invalid name)" for this task.
*/
public static PerfMarkTask taskWithMinPeriod(
PerfTag tag, long minPeriodNanos, @CompileTimeConstant String taskName) {
return AUTO_DO_NOTHING;
}
/**
* Start a Task with time threshold in a try-with-resource statement; a task represents some work
* that spans some time, and you are interested in both its start time and end time.
*
* <p>Use this in a try-with-resource statement so that task will end automatically.
*
* <p>Sometimes, you may be interested in only events that take more than a certain time
* threshold. In such cases, you can use this method. A task that takes less than the specified
* threshold, along with all its sub-tasks, events, and additional tags will be discarded.
*
* @param minPeriodNanos Tasks that takes less than the specified time period, in nanosecond, will
* be discarded, along with its sub-tasks, events, and additional tags.
* @param taskName The name of the task. <b>This parameter must be a compile-time constant!</b>
* Otherwise, instrumentation result will show "(invalid name)" for this task.
*/
public static PerfMarkTask taskWithMinPeriod(
long minPeriodNanos, @CompileTimeConstant String taskName) {
return AUTO_DO_NOTHING;
}
static final PerfMarkTask AUTO_DO_NOTHING = new PerfMarkTask() {
@Override
public void close() {}
};
/**
* Records an Event with a Tag to identify it.
*
@ -197,18 +129,43 @@ public final class PerfMark {
public static void event(@CompileTimeConstant String eventName) {}
/**
* Add an additional tag to the last task that was started.
* If PerfMark instrumentation is not enabled, returns a Tag with numericTag = 0L. Replacement
* for {@link TagFactory#create(long, String)} if PerfMark agent is enabled.
*
* <p>A tag is different from an Event or a task in that clients don't care about the time at
* which this tag is added. Instead, it allows clients to associate an additional tag to the
* current Task.
*
* @param tag a Tag object associated with the task. See {@link PerfTag} for description. Don't
* use 0 for the {@code numericTag} of the Tag object. 0 is reserved to represent that a task
* does not have a numeric tag associated. In this case, you are encouraged to use {@link
* PerfTag#create(String)}.
* @param tagName The name of the tag. <b>This parameter must be a compile-time constant!</b>
* Otherwise, instrumentation result will show "(invalid name)" for this tag.
*/
public static void tag(PerfTag tag, @CompileTimeConstant String tagName) {}
public static PerfTag createTag(
@SuppressWarnings("unused") long numericTag, @SuppressWarnings("unused") String stringTag) {
// Warning suppression is safe as this method returns by default the NULL_PERF_TAG
return NULL_PERF_TAG;
}
/**
* If PerfMark instrumentation is not enabled returns a Tag with numericTag = 0L. Replacement
* for {@link TagFactory#create(String)} if PerfMark agent is enabled.
*/
public static PerfTag createTag(@SuppressWarnings("unused") String stringTag) {
// Warning suppression is safe as this method returns by default the NULL_PERF_TAG
return NULL_PERF_TAG;
}
/**
* If PerfMark instrumentation is not enabled returns a Tag with numericTag = 0L. Replacement
* for {@link TagFactory#create(long)} if PerfMark agent is enabled.
*/
public static PerfTag createTag(@SuppressWarnings("unused") long numericTag) {
// Warning suppression is safe as this method returns by default the NULL_PERF_TAG
return NULL_PERF_TAG;
}
private static final PerfTag NULL_PERF_TAG = TagFactory.create();
private static final class NoopTask extends PerfMarkTask {
private static final PerfMarkTask INSTANCE = new NoopTask();
NoopTask() {}
@Override
public void close() {}
}
}

View File

@ -16,6 +16,9 @@
package io.grpc.perfmark;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* A Tag is used to provide additional information to identify a task and consists of a 64-bit
* integer value and a string.
@ -34,74 +37,27 @@ package io.grpc.perfmark;
* <p>This class is {@link io.grpc.Internal} and {@link io.grpc.ExperimentalApi}. Do not use this
* yet.
*/
@Immutable
public final class PerfTag {
private static final long NULL_NUMERIC_TAG = 0;
private static final String NULL_STRING_TAG = "";
private static final PerfTag NULL_PERF_TAG = TagFactory.create(NULL_NUMERIC_TAG, NULL_STRING_TAG);
/**
* If PerfMark instrumentation is not enabled, returns a Tag with numericTag = 0L. Replacement
* for {@link TagFactory#create(long, String)} if PerfMark agent is enabled.
*/
public static PerfTag create(
@SuppressWarnings("unused") long numericTag, @SuppressWarnings("unused") String stringTag) {
// Warning suppression is safe as this method returns by default the NULL_TAG
return NULL_PERF_TAG;
}
/**
* If PerfMark instrumentation is not enabled returns a Tag with numericTag = 0L. Replacement
* for {@link TagFactory#create(String)} if PerfMark agent is enabled.
*/
public static PerfTag create(@SuppressWarnings("unused") String stringTag) {
// Warning suppression is safe as this method returns by default the NULL_TAG
return NULL_PERF_TAG;
}
/**
* If PerfMark instrumentation is not enabled returns a Tag with numericTag = 0L. Replacement
* for {@link TagFactory#create(long)} if PerfMark agent is enabled.
*/
public static PerfTag create(@SuppressWarnings("unused") long numericTag) {
// Warning suppression is safe as this method returns by default the NULL_TAG
return NULL_PERF_TAG;
}
/**
* Returns the null tag.
*/
public static PerfTag create() {
return NULL_PERF_TAG;
}
/**
* Allocates a unique, mostly sequential unique id for Tags. This method will be replaced with
* a call to a real implementation if instrumentation is enabled.
*/
public static final long allocateNumericId() {
return NULL_NUMERIC_TAG;
}
private static final String NULL_STRING_TAG = null;
private final long numericTag;
private final String stringTag;
private PerfTag(long numericTag, String stringTag) {
private PerfTag(long numericTag, @Nullable String stringTag) {
this.numericTag = numericTag;
if (stringTag == null) {
throw new NullPointerException("stringTag");
}
this.stringTag = stringTag;
}
/** Returns the numeric tag if set, or {@link Constants#NULL_NUMERIC_TAG} instead. */
/** Returns the numeric tag if set, or {@link #NULL_NUMERIC_TAG} instead. */
public long getNumericTag() {
return numericTag;
}
/** Returns the string tag if set, or {@link Constants#NULL_STRING_TAG} instead. */
public String getStringTag() {
/** Returns the string tag if set, or {@link #NULL_STRING_TAG} instead. */
@Nullable public String getStringTag() {
return stringTag;
}
@ -117,30 +73,30 @@ public final class PerfTag {
}
@Override
@SuppressWarnings("ReferenceEquality") // No Java 8 yet.
public boolean equals(Object obj) {
if (!(obj instanceof PerfTag)) {
return false;
}
PerfTag other = (PerfTag) obj;
return this.numericTag == other.numericTag && this.stringTag.equals(other.stringTag);
PerfTag that = (PerfTag) obj;
return numericTag == that.numericTag
&& (stringTag == that.stringTag || (stringTag != null && stringTag.equals(that.stringTag)));
}
/**
* Provides methods that create Tag instances which should not be directly invoked by clients.
*
* <p><b>Warning:</b> Clients should not call methods from this class directly because of the
* overhead involved in the creation of Tag objects when PerfMark instrumentation is not
* enabled.
*
* <p>Calls to {@link PerfTag#create(long)}, {@link PerfTag#create(long, String)} and {@link
* PerfTag#create(String)} are replaced with calls to the methods in this class using bytecode
* <p>Calls to {@link PerfMark#create(long)}, {@link PerfMark#create(long, String)} and {@link
* PerfMark#create(String)} are replaced with calls to the methods in this class using bytecode
* rewriting, if enabled.
*/
static final class TagFactory {
/**
* This class should not be instantiated.
*/
private TagFactory() {}
private TagFactory() {
throw new AssertionError("nope");
}
public static PerfTag create(long numericTag, String stringTag) {
return new PerfTag(numericTag, stringTag);
@ -153,6 +109,10 @@ public final class PerfTag {
public static PerfTag create(long numericTag) {
return new PerfTag(numericTag, NULL_STRING_TAG);
}
static PerfTag create() {
return new PerfTag(NULL_NUMERIC_TAG, NULL_STRING_TAG);
}
}
}

View File

@ -16,6 +16,9 @@
/**
* This is an internal, experimental API and not subject to the normal compatibility guarantees.
*
* @see io.grpc.Internal
*/
@io.grpc.Internal
@javax.annotation.CheckReturnValue
@javax.annotation.ParametersAreNonnullByDefault
package io.grpc.perfmark;