Class PerfMark
- java.lang.Object
-
- io.perfmark.PerfMark
-
public final class PerfMark extends java.lang.Object
PerfMark is a very low overhead tracing library. To use PerfMark, annotate the code that needs to be traced using the start and stop methods. For example:try (var close = PerfMark.traceTask("parseMessage")) { message = parse(bytes); }
When PerfMark is enabled, these tracing calls will record the start and stop times of the given task. When disabled, PerfMark disables these tracing calls, resulting in no additional tracing overhead. PerfMark can be enabled or disabled using the
setEnabled(boolean)
. By default, PerfMark starts off disabled. PerfMark can be automatically enabled by setting the System propertyio.perfmark.PerfMark.startEnabled
to true.Tasks represent the span of work done by some code, starting and stopping in the same thread. Each task is started using one of the
startTask
methods, and ended using one ofstopTask
methods. Each start must have a corresponding stop. While not required, it is good practice for the start and stop calls have matching arguments for clarity. Tasks form a "tree", with each child task starting after the parent has started, and stopping before the parent has stopped. The most recently started (and not yet stopped) task is used by the tagging and linking commands described below.Tags are metadata about the task. Each
Tag
contains a String and/or a long that describes the task, such as an RPC name, or request ID. When PerfMark is disabled, the Tag objects are not created, avoiding overhead. Tags are useful for keeping track of metadata about a task(s) that doesn't change frequently, or needs to be applied at multiple layers. In addition to Tag objects, named-tags can be added to the current task using theattachTag
methods. These allow including key-value like metadata with the task.Links allow the code to represent relationships between different threads. When one thread initiates work for another thread (such as a callback), Links express the control flow. For example:
try (var close = PerfMark.traceTask("handleMessage")) { Link link = PerfMark.linkOut(); var message = parse(bytes); executor.execute(() -> { try (var closeInner = PerfMark.traceTask("processMessage")) { PerfMark.linkIn(link); handle(message); } }); }
Links are created inside the scope of the current task and are linked into the scope of another task. PerfMark will represent the causal relationship between these two tasks. Links have a many-many relationship, and can be reused. Like Tasks and Tags, when PerfMark is disabled, the Links returned are no-op implementations.
Events are a special kind of Task, which do not have a duration. In effect, they only have a single timestamp the represents a particular occurrence. Events are slightly more efficient than tasks while PerfMark is enabled, but cannot be used with Links or named-tags.
-
-
Constructor Summary
Constructors Modifier Constructor Description private
PerfMark()
-
Method Summary
All Methods Static Methods Concrete Methods Deprecated Methods Modifier and Type Method Description static <T> void
attachIntTag(java.lang.String tagName, T tagObject, java.util.function.ToIntFunction<? super T> intFunction)
Attaches an additional keyed tag to the current active task.static <T> void
attachLongTag(java.lang.String tagName, T tagObject, java.util.function.ToLongFunction<? super T> longFunction)
Attaches an additional keyed tag to the current active task.static <T> void
attachStringTag(java.lang.String tagName, T tagObject, java.util.function.Function<? super T,? extends java.lang.String> stringFunction)
Attaches an additional keyed tag to the current active task.static void
attachTag(Tag tag)
Attaches an additional tag to the current active task.static void
attachTag(java.lang.String tagName, long tagValue)
Attaches an additional keyed tag to the current active task.static void
attachTag(java.lang.String tagName, long tagValue0, long tagValue1)
Attaches an additional keyed tag to the current active task.static void
attachTag(java.lang.String tagName, java.lang.String tagValue)
Attaches an additional keyed tag to the current active task.static <T> void
attachTag(java.lang.String tagName, T tagObject, StringFunction<? super T> stringFunction)
Attaches an additional keyed tag to the current active task.static Tag
createTag()
Creates a tag with no name or numeric identifier.static Tag
createTag(long id)
Creates a tag with no name.static Tag
createTag(java.lang.String name)
Creates a tag with no numeric identifier.static Tag
createTag(java.lang.String name, long id)
Creates a tag with both a name and a numeric identifier.static void
event(java.lang.String eventName)
Marks an event.static void
event(java.lang.String eventName, Tag tag)
Marks an event.static void
event(java.lang.String eventName, java.lang.String subEventName)
Marks an event.static Link
link()
Deprecated.static void
linkIn(Link link)
Associate this link with the most recently started task.static Link
linkOut()
A link connects between two tasks that start asynchronously.static boolean
setEnabled(boolean value)
Turns on or off PerfMark recording.static void
startTask(java.lang.String taskName)
Marks the beginning of a task.static void
startTask(java.lang.String taskName, Tag tag)
Marks the beginning of a task.static void
startTask(java.lang.String taskName, java.lang.String subTaskName)
Marks the beginning of a task.static <T> void
startTask(T taskNameObject, StringFunction<? super T> taskNameFunction)
Marks the beginning of a task.static void
stopTask()
Marks the end of a task.static void
stopTask(java.lang.String taskName)
Marks the end of a task.static void
stopTask(java.lang.String taskName, Tag tag)
Marks the end of a task.static void
stopTask(java.lang.String taskName, java.lang.String subTaskName)
Marks the end of a task.static TaskCloseable
traceTask(java.lang.String taskName)
Marks the beginning of a task.static <T> TaskCloseable
traceTask(T taskNameObject, StringFunction<? super T> taskNameFunction)
Marks the beginning of a task.
-
-
-
Field Detail
-
impl
private static final Impl impl
-
-
Method Detail
-
setEnabled
public static boolean setEnabled(boolean value)
Turns on or off PerfMark recording. Don't call this method too frequently; while neither on nor off have very high overhead, transitioning between the two may be slow.- Parameters:
value
-true
to enable PerfMark recording, orfalse
to disable it.- Returns:
- If the enabled value was changed.
- Since:
- 0.13.37
-
startTask
public static void startTask(java.lang.String taskName, Tag tag)
Marks the beginning of a task. If PerfMark is disabled, this method is a no-op. The name of the task should be a runtime-time constant, usually a string literal. Tasks with the same name can be grouped together for analysis later, so avoid using too many unique task names.The tag is a run-time identifier for the task. It represents the dynamic part of the task, while the task name is the constant part of the task. While not always enforced, tags should not be
null
.- Parameters:
taskName
- the name of the task.tag
- a user provided tag for the task.- Since:
- 0.13.37
-
startTask
public static void startTask(java.lang.String taskName)
Marks the beginning of a task. If PerfMark is disabled, this method is a no-op. The name of the task should be a runtime-time constant, usually a string literal. Tasks with the same name can be grouped together for analysis later, so avoid using too many unique task names.- Parameters:
taskName
- the name of the task.- Since:
- 0.13.37
-
startTask
public static <T> void startTask(T taskNameObject, StringFunction<? super T> taskNameFunction)
Marks the beginning of a task. If PerfMark is disabled, this method is a no-op. The name of the task should be a runtime-time constant, usually a string literal. Tasks with the same name can be grouped together for analysis later, so avoid using too many unique task names.This function has many more caveats than the
startTask(String)
that accept a string. See the docs atattachTag(String, Object, StringFunction)
for a list of risks associated with passing a function.- Type Parameters:
T
- the object type to be stringified- Parameters:
taskNameObject
- the name of the task.taskNameFunction
- the function that will convert the taskNameObject to a taskName- Since:
- 0.22.0
-
startTask
public static void startTask(java.lang.String taskName, java.lang.String subTaskName)
Marks the beginning of a task. If PerfMark is disabled, this method is a no-op. The names of the task and subtask should be runtime-time constants, usually a string literal. Tasks with the same name can be grouped together for analysis later, so avoid using too many unique task names.- Parameters:
taskName
- the name of the task.subTaskName
- the name of the sub task- Since:
- 0.20.0
-
traceTask
@MustBeClosed @CheckReturnValue public static TaskCloseable traceTask(java.lang.String taskName)
Marks the beginning of a task. If PerfMark is disabled, this method is a no-op. The name of the task should be a runtime-time constant, usually a string literal. Tasks with the same name can be grouped together for analysis later, so avoid using too many unique task names.The returned closeable is meant to be used in a try-with-resources block. Callers should not allow the returned closeable to be used outside of the try block that initiated the call. Unlike other closeables, it is not safe to call close() more than once.
- Parameters:
taskName
- the name of the task.- Returns:
- a closeable that must be closed at the end of the task
- Since:
- 0.23.0
-
traceTask
@MustBeClosed @CheckReturnValue public static <T> TaskCloseable traceTask(T taskNameObject, StringFunction<? super T> taskNameFunction)
Marks the beginning of a task. If PerfMark is disabled, this method is a no-op. The name of the task should be a runtime-time constant, usually a string literal. Tasks with the same name can be grouped together for analysis later, so avoid using too many unique task names.This function has many more caveats than the
traceTask(String)
that accept a string. See the docs atattachTag(String, Object, StringFunction)
for a list of risks associated with passing a function. Unlike other closeables, it is not safe to call close() more than once.- Type Parameters:
T
- the object type to be stringified- Parameters:
taskNameObject
- the name of the task.taskNameFunction
- the function that will convert the taskNameObject to a taskName- Returns:
- a closeable that must be closed at the end of the task
- Since:
- 0.23.0
-
event
public static void event(java.lang.String eventName, Tag tag)
Marks an event. Events are logically both a task start and a task end. Events have no duration associated. Events still represent the instant something occurs. If PerfMark is disabled, this method is a no-op.The tag is a run-time identifier for the event. It represents the dynamic part of the event, while the event name is the constant part of the event. While not always enforced, tags should not be
null
.- Parameters:
eventName
- the name of the event.tag
- a user provided tag for the event.- Since:
- 0.13.37
-
event
public static void event(java.lang.String eventName)
Marks an event. Events are logically both a task start and a task end. Events have no duration associated. Events still represent the instant something occurs. If PerfMark is disabled, this method is a no-op.- Parameters:
eventName
- the name of the event.- Since:
- 0.13.37
-
event
public static void event(java.lang.String eventName, java.lang.String subEventName)
Marks an event. Events are logically both a task start and a task end. Events have no duration associated. Events still represent the instant something occurs. If PerfMark is disabled, this method is a no-op.- Parameters:
eventName
- the name of the event.subEventName
- the name of the sub event.- Since:
- 0.20.0
-
stopTask
public static void stopTask()
Marks the end of a task. If PerfMark is disabled, this method is a no-op.It is important that
stopTask()
always be called after starting a task, even in case of exceptions. Failing to do so may result in corrupted results.- Since:
- 0.22.0
-
stopTask
public static void stopTask(java.lang.String taskName, Tag tag)
Marks the end of a task. If PerfMark is disabled, this method is a no-op. The task name and tag should match the ones provided to the correspondingstartTask(String, Tag)
, if provided. If the task name or tag do not match, the implementation will prefer the starting name and tag. The name and tag help identify the task if PerfMark is enabled mid way through the task, or if the previous results have been overwritten. The name of the task should be a runtime-time constant, usually a string literal. Consider usingstopTask()
instead.It is important that
stopTask()
always be called after starting a task, even in case of exceptions. Failing to do so may result in corrupted results.- Parameters:
taskName
- the name of the task being ended.tag
- the tag of the task being ended.- Since:
- 0.13.37
-
stopTask
public static void stopTask(java.lang.String taskName)
Marks the end of a task. If PerfMark is disabled, this method is a no-op. The task name should match the ones provided to the correspondingstartTask(String)
, if provided. If the task name does not match, the implementation will prefer the starting name. The name helps identify the task if PerfMark is enabled mid way through the task, or if the previous results have been overwritten. The name of the task should be a runtime-time constant, usually a string literal. Consider usingstopTask()
instead.It is important that
stopTask()
always be called after starting a task, even in case of exceptions. Failing to do so may result in corrupted results.- Parameters:
taskName
- the name of the task being ended.- Since:
- 0.13.37
-
stopTask
public static void stopTask(java.lang.String taskName, java.lang.String subTaskName)
Marks the end of a task. If PerfMark is disabled, this method is a no-op. The task name should match the ones provided to the correspondingstartTask(String, String)
, if provided. If the task name does not match, the implementation will prefer the starting name. The name helps identify the task if PerfMark is enabled mid way through the task, or if the previous results have been overwritten. The name of the task should be a runtime-time constant, usually a string literal. Consider usingstopTask()
instead.It is important that
stopTask()
always be called after starting a task, even in case of exceptions. Failing to do so may result in corrupted results.- Parameters:
taskName
- the name of the task being ended.subTaskName
- the name of the sub task being ended.- Since:
- 0.20.0
-
createTag
public static Tag createTag()
Creates a tag with no name or numeric identifier. The returned instance is different based on if PerfMark is enabled or not.This method is seldomly useful; users should generally prefer to use the overloads of methods that don't need a tag. An empty tag may be useful though when the tag of a group of tasks may change over time.
- Returns:
- a Tag that has no name or id.
- Since:
- 0.13.37
-
createTag
public static Tag createTag(long id)
Creates a tag with no name. The returned instance is different based on if PerfMark is enabled or not. The provided id does not have to be globally unique, but is instead meant to give context to a task.- Parameters:
id
- a user provided identifier for this Tag.- Returns:
- a Tag that has no name.
- Since:
- 0.13.37
-
createTag
public static Tag createTag(java.lang.String name)
Creates a tag with no numeric identifier. The returned instance is different based on if PerfMark is enabled or not. The provided name does not have to be globally unique, but is instead meant to give context to a task.- Parameters:
name
- a user provided name for this Tag.- Returns:
- a Tag that has no numeric identifier.
- Since:
- 0.13.37
-
createTag
public static Tag createTag(java.lang.String name, long id)
Creates a tag with both a name and a numeric identifier. The returned instance is different based on if PerfMark is enabled or not. Neither the provided name nor id has to be globally unique, but are instead meant to give context to a task.- Parameters:
id
- a user provided identifier for this Tag.name
- a user provided name for this Tag.- Returns:
- a Tag that has both a name and id.
- Since:
- 0.13.37
-
link
@Deprecated public static Link link()
Deprecated.DO NOT CALL, no longer implemented. UselinkOut()
instead.- Returns:
- a no-op link that
-
linkOut
public static Link linkOut()
A link connects between two tasks that start asynchronously. WhenlinkOut()
is called, an association between the most recently started task and a yet-to-be named task on another thread, is created. Links are a one-to-many relationship. A single started task can have multiple associated tasks on other threads.- Returns:
- A Link to be used in other tasks.
- Since:
- 0.17.0
-
linkIn
public static void linkIn(Link link)
Associate this link with the most recently started task. There may be at most one inbound linkage per task: the first call tolinkIn(io.perfmark.Link)
decides which outbound task is the origin.- Parameters:
link
- a link created inside of another task.- Since:
- 0.17.0
-
attachTag
public static void attachTag(Tag tag)
Attaches an additional tag to the current active task. The tag provided is independent of the tag used withstartTask(String, Tag)
andstopTask(String, Tag)
. Unlike the two previous two task overloads, the tag provided toattachTag(Tag)
does not have to match any other tags in use. This method is useful for when you have the tag information after the task is started.Here are some example usages:
Recording the amount of work done in a task:
byte[] data; try (var close = PerfMark.traceTask("read")) { data = file.read(); PerfMark.attachTag(PerfMark.createTag("bytes read", data.length)); }
Recording a tag which may be absent on an exception:
Socket s; Tag remoteTag = PerfMark.createTag(remoteAddress.toString()); PerfMark.startTask("connect", remoteTag); try { s = connect(remoteAddress); PerfMark.attachTag(PerfMark.createTag(s.getLocalAddress().toString()); } finally { PerfMark.stopTask("connect", remoteTag); }
- Parameters:
tag
- the Tag to attach.- Since:
- 0.18.0
-
attachTag
public static void attachTag(java.lang.String tagName, java.lang.String tagValue)
Attaches an additional keyed tag to the current active task. The tag provided is independent of the tag used withstartTask
andstopTask
. This tag operation is different thanTag
in that the tag value has an associated name (also called a key). The tag name and value are attached to the most recently started task, and don't have to match any other tags. This method is useful for when you have the tag information after the task is started.- Parameters:
tagName
- The name of the value being attachedtagValue
- The value to attach to the current task.- Since:
- 0.20.0
-
attachTag
public static void attachTag(java.lang.String tagName, long tagValue)
Attaches an additional keyed tag to the current active task. The tag provided is independent of the tag used withstartTask
andstopTask
. This tag operation is different thanTag
in that the tag value has an associated name (also called a key). The tag name and value are attached to the most recently started task, and don't have to match any other tags. This method is useful for when you have the tag information after the task is started.- Parameters:
tagName
- The name of the value being attachedtagValue
- The value to attach to the current task.- Since:
- 0.20.0
-
attachTag
public static void attachTag(java.lang.String tagName, long tagValue0, long tagValue1)
Attaches an additional keyed tag to the current active task. The tag provided is independent of the tag used withstartTask
andstopTask
. This tag operation is different thanTag
in that the tag values have an associated name (also called a key). The tag name and values are attached to the most recently started task, and don't have to match any other tags. This method is useful for when you have the tag information after the task is started.This method may treat the given two longs as special. If the tag name contains the string "uuid" (case-insensitive), the value may be treated as a single 128 bit value. An example usage:
RPC rpc = ... PerfMark.startTask("sendRPC"); try { UUID u = rpc.uuid(); PerfMark.attachTag("rpc uuid", u.getMostSignificantBits(), u.getLeastSignificantBits()); send(rpc); } finally { PerfMark.stopTask("sendRPC"); }
- Parameters:
tagName
- The name of the value being attachedtagValue0
- The first value to attach to the current task.tagValue1
- The second value to attach to the current task.- Since:
- 0.20.0
-
attachStringTag
public static <T> void attachStringTag(java.lang.String tagName, T tagObject, java.util.function.Function<? super T,? extends java.lang.String> stringFunction)
Attaches an additional keyed tag to the current active task. The tag provided is independent of the tag used withstartTask
andstopTask
. This tag operation is different thanTag
in that the tag value has an associated name (also called a key). The tag name and value are attached to the most recently started task, and don't have to match any other tags. This method is useful for when you have the tag information after the task is started.Unlike
attachTag(String, String)
, this defers constructing the tagValue String until later, and avoids doing any work while PerfMark is disabled. Callers are expected to provide a method handle that can consume thetagObject
, and produce a tagValue. For example:Response resp = client.makeCall(request); PerfMark.attachTag("httpServerHeader", resp, r -> r.getHeaders().get("Server"));
Also unlike
attachTag(String, String)
, this function is easier to misuse. Prefer using the other attachTag methods unless you are confident you need this one. Be familiar with following issues:- Callers should be careful to not capture the
tagObject
, and instead use the argument tostringFunction
. This avoids a memory allocation and possibly holding the tagObject alive longer than necessary. - The
stringFunction
should be idempotent, have no side effects, and be safe to invoke from other threads. If the string function references state that may be changed, callers must synchronize access. The string function may be called multiple times for the same tag object. Additionally, ifattachTag()
is called with the same tag object and string function multiple times, PerfMark may invoke the function only once. - The tag object may kept alive longer than normal, and prevent garbage collection from reclaiming it. If the tag object retains a large amount of resources, this may appear as a memory leak. The risk of this memory increase will need to be balanced with the cost of eagerly constructing the tag value string. Additionally, if the string function is a capturing lambda (refers to local or global state), the function itself may appear as a leak.
- If the stringFunction is
null
, or if it throws an exception when called, the tag value will not be attached. It is implementation defined if such problems are reported (e.g. logged). Note that exceptions are expensive compared to PerfMark calls, and thus may slow down tracing. If an exception is thrown, or if the stringFunction isnull
, PerfMark may invoke other methods on the tag object or string function, such astoString()
andgetClass()
.
- Type Parameters:
T
- the type of tag object to be stringified- Parameters:
tagName
- The name of the value being attachedtagObject
- The tag object which will passed to the stringFunction.stringFunction
- The function that will convert the object to a tag- Since:
- 0.27.0
- Callers should be careful to not capture the
-
attachTag
public static <T> void attachTag(java.lang.String tagName, T tagObject, StringFunction<? super T> stringFunction)
Attaches an additional keyed tag to the current active task. The tag provided is independent of the tag used withstartTask
andstopTask
. This tag operation is different thanTag
in that the tag value has an associated name (also called a key). The tag name and value are attached to the most recently started task, and don't have to match any other tags. This method is useful for when you have the tag information after the task is started.Prefer
attachStringTag(String, Object, Function)
over this one.- Type Parameters:
T
- the type of tag object to be stringified- Parameters:
tagName
- The name of the value being attachedtagObject
- The tag object which will passed to the stringFunction.stringFunction
- The function that will convert the object to a tag- Since:
- 0.22.0
-
attachIntTag
public static <T> void attachIntTag(java.lang.String tagName, T tagObject, java.util.function.ToIntFunction<? super T> intFunction)
Attaches an additional keyed tag to the current active task. The tag provided is independent of the tag used withstartTask
andstopTask
. This tag operation is different thanTag
in that the tag value has an associated name (also called a key). The tag name and value are attached to the most recently started task, and don't have to match any other tags. This method is useful for when you have the tag information after the task is started.- Type Parameters:
T
- the type of tag object to mapped to in.- Parameters:
tagName
- The name of the value being attachedtagObject
- The tag object which will passed to the intFunction.intFunction
- The function that will convert the object to a tag- Since:
- 0.27.0
-
attachLongTag
public static <T> void attachLongTag(java.lang.String tagName, T tagObject, java.util.function.ToLongFunction<? super T> longFunction)
Attaches an additional keyed tag to the current active task. The tag provided is independent of the tag used withstartTask
andstopTask
. This tag operation is different thanTag
in that the tag value has an associated name (also called a key). The tag name and value are attached to the most recently started task, and don't have to match any other tags. This method is useful for when you have the tag information after the task is started.- Type Parameters:
T
- the type of tag object to mapped to in.- Parameters:
tagName
- The name of the value being attachedtagObject
- The tag object which will passed to the intFunction.longFunction
- The function that will convert the object to a tag- Since:
- 0.27.0
-
-