xref: /aosp_15_r20/external/perfmark/README.md (revision 27e8546d0ef5f99cf83d5252272c7dd38d18d29a)
1*27e8546dSMatt Gilbride# PerfMark
2*27e8546dSMatt Gilbride
3*27e8546dSMatt Gilbride![PerfMark Hummingbird](doc/perfmark.png "PerfMark")
4*27e8546dSMatt Gilbride
5*27e8546dSMatt GilbridePerfMark is a low-overhead, manually-instrumented, tracing library for Java.  Users can add the
6*27e8546dSMatt Gilbridetracing function calls to their code to see how long each part takes.
7*27e8546dSMatt Gilbride
8*27e8546dSMatt Gilbride## Features
9*27e8546dSMatt Gilbride
10*27e8546dSMatt Gilbride*   **Very Low Overhead**:  When enabled, tracing a function call adds about **70ns**.   Tracing is
11*27e8546dSMatt Gilbride    done in a lock-free, wait-free, thread local buffer, which avoids interfering with your
12*27e8546dSMatt Gilbride    latency-sensitive code.
13*27e8546dSMatt Gilbride
14*27e8546dSMatt Gilbride*   **Dynamically Enabled**: PerfMark can be enabled or disabled at runtime.  When disabled,
15*27e8546dSMatt Gilbride    PerfMark has *zero overhead*, taking advantage of the JIT compiler to remove the tracing.
16*27e8546dSMatt Gilbride
17*27e8546dSMatt Gilbride*   **Inter-thread Communication**: Existing profilers have difficulty expressing which thread
18*27e8546dSMatt Gilbride    wakes up and executes work on another thread.  PerfMark allows users to express this
19*27e8546dSMatt Gilbride    relationship explicitly, making for a clear picture of how code flows.
20*27e8546dSMatt Gilbride
21*27e8546dSMatt Gilbride*   **Small Library Size**: The PerfMark tracing API is only *5 KB* in size, and has minimal
22*27e8546dSMatt Gilbride    dependencies making it easy to include in other projects.  If no backend for recording the trace
23*27e8546dSMatt Gilbride    is present, the library safely disables itself.
24*27e8546dSMatt Gilbride
25*27e8546dSMatt Gilbride*   **Multiple Java Versions**: The PerfMark API supports Java 6, making it easy to include on
26*27e8546dSMatt Gilbride    older or constrained environments.  Additionally, PerfMark includes optimized backends for
27*27e8546dSMatt Gilbride    Java 6, Java 7, and Java 9.  Each of these backends is automatically loaded at runtime
28*27e8546dSMatt Gilbride    (if possible) and uses advanced JVM features for maximum speed.
29*27e8546dSMatt Gilbride
30*27e8546dSMatt Gilbride*   **Chrome Trace Viewer Integration**: PerfMark can export to the Chrome Trace Event Format,
31*27e8546dSMatt Gilbride    making it easy to view in your Web Browser.
32*27e8546dSMatt Gilbride
33*27e8546dSMatt Gilbride## Usage
34*27e8546dSMatt Gilbride
35*27e8546dSMatt GilbrideTo use PerfMark, add the following dependencies to your `build.gradle`:
36*27e8546dSMatt Gilbride```
37*27e8546dSMatt Gilbridedependencies {
38*27e8546dSMatt Gilbride    implementation 'io.perfmark:perfmark-api:0.25.0'
39*27e8546dSMatt Gilbride    // Only needed for applications, not libraries.
40*27e8546dSMatt Gilbride    implementation 'io.perfmark:perfmark-traceviewer:0.25.0'
41*27e8546dSMatt Gilbride}
42*27e8546dSMatt Gilbride```
43*27e8546dSMatt Gilbride
44*27e8546dSMatt GilbrideOr in your `pom.xml`:
45*27e8546dSMatt Gilbride
46*27e8546dSMatt Gilbride```
47*27e8546dSMatt Gilbride    <dependency>
48*27e8546dSMatt Gilbride      <groupId>io.perfmark</groupId>
49*27e8546dSMatt Gilbride      <artifactId>perfmark-api</artifactId>
50*27e8546dSMatt Gilbride      <version>0.25.0</version>
51*27e8546dSMatt Gilbride    </dependency>
52*27e8546dSMatt Gilbride```
53*27e8546dSMatt Gilbride
54*27e8546dSMatt GilbrideIn your code, add the PerfMark tracing calls like so:
55*27e8546dSMatt Gilbride
56*27e8546dSMatt Gilbride```java
57*27e8546dSMatt GilbrideMap<String, Header> parseHeaders(List<String> rawHeaders) {
58*27e8546dSMatt Gilbride  try (TaskCloseable task = PerfMark.traceTask("Parse HTTP headers")) {
59*27e8546dSMatt Gilbride    Map<String, String> headers = new HashMap<>();
60*27e8546dSMatt Gilbride    for (String rawHeader : rawHeaders) {
61*27e8546dSMatt Gilbride      Header header = parseHeader(rawHeader);
62*27e8546dSMatt Gilbride      headers.put(header.name(), header);
63*27e8546dSMatt Gilbride    }
64*27e8546dSMatt Gilbride    return headers;
65*27e8546dSMatt Gilbride  }
66*27e8546dSMatt Gilbride}
67*27e8546dSMatt Gilbride
68*27e8546dSMatt Gilbride```
69*27e8546dSMatt Gilbride
70*27e8546dSMatt GilbridePerfMark can also be used to record asynchronous work:
71*27e8546dSMatt Gilbride
72*27e8546dSMatt Gilbride```java
73*27e8546dSMatt GilbrideFuture<Response> buildResponse() {
74*27e8546dSMatt Gilbride  try (TaskCloseable task = PerfMark.traceTask("Build Response")) {
75*27e8546dSMatt Gilbride    Link link = PerfMark.linkOut();
76*27e8546dSMatt Gilbride    return executor.submit(() -> {
77*27e8546dSMatt Gilbride      try (TaskCloseable task2 = PerfMark.traceTask("Async Response")) {
78*27e8546dSMatt Gilbride        PerfMark.linkIn(link);
79*27e8546dSMatt Gilbride        return new Response(/* ... */);
80*27e8546dSMatt Gilbride      }
81*27e8546dSMatt Gilbride    });
82*27e8546dSMatt Gilbride  }
83*27e8546dSMatt Gilbride}
84*27e8546dSMatt Gilbride```
85*27e8546dSMatt Gilbride
86*27e8546dSMatt GilbrideTo view the traces in your browser, generate the HTML:
87*27e8546dSMatt Gilbride
88*27e8546dSMatt Gilbride```java
89*27e8546dSMatt Gilbride  PerfMark.setEnabled(true);
90*27e8546dSMatt Gilbride  PerfMark.event("My Task");
91*27e8546dSMatt Gilbride  TraceEventViewer.writeTraceHtml();
92*27e8546dSMatt Gilbride```
93*27e8546dSMatt Gilbride
94*27e8546dSMatt GilbrideThe output looks like:
95*27e8546dSMatt Gilbride
96*27e8546dSMatt Gilbride![PerfMark Hummingbird](doc/screenshot.png "PerfMark")
97*27e8546dSMatt Gilbride
98*27e8546dSMatt Gilbride## Configuration
99*27e8546dSMatt GilbridePerfMark provides some System Properties that allow controlling how it initializes.  These can be set
100*27e8546dSMatt Gilbrideby providing them as JVM arguments.  (e.g. `-Dio.perfmark.PerfMark.startEnabled=true`)
101*27e8546dSMatt Gilbride
102*27e8546dSMatt Gilbride* `io.perfmark.PerfMark.startEnabled` controls if PerfMark starts enabled.  This boolean property
103*27e8546dSMatt Gilbride    makes it possible to start tracing calls immediately.  This is helpful when it's difficult
104*27e8546dSMatt Gilbride    to invoke `setEnabled()` on PerfMark before task tracing calls have started.
105*27e8546dSMatt Gilbride
106*27e8546dSMatt Gilbride* `io.perfmark.PerfMark.debug` controls if PerfMark can log initializing steps.  This property
107*27e8546dSMatt Gilbride    exists to disable class loading of the logger package (currently `java.util.logging`).  If
108*27e8546dSMatt Gilbride    the debug property is set, the logger settings still need to be configured to report the logs.
109*27e8546dSMatt Gilbride    By default, all PerfMark logs use level `FINE` (SLF4J `DEBUG`) or lower, which means that they
110*27e8546dSMatt Gilbride    usually need additional setup to print.
111*27e8546dSMatt Gilbride
112*27e8546dSMatt Gilbride    In addition to initialization, the debug property controls if other tracing failures can be
113*27e8546dSMatt Gilbride    logged. When calls involving deferred execution are used (e.g.
114*27e8546dSMatt Gilbride    `startTask(T, StringFunction<T>)`), the String function provided may throw an exception.  In
115*27e8546dSMatt Gilbride    these cases, the exception is silently ignored.  This makes it easy to ensure the start/stop
116*27e8546dSMatt Gilbride    call parity is maintained.  To view these failures, the debug property can be set to log such
117*27e8546dSMatt Gilbride    problems.  As above, the PerfMark logger should be configured as well to report these.
118*27e8546dSMatt Gilbride
119*27e8546dSMatt Gilbride## Versioning and API Stability
120*27e8546dSMatt Gilbride
121*27e8546dSMatt GilbridePerfMark uses Semantic Versioning, and thus will not break existing APIs within a minor version
122*27e8546dSMatt Gilbrideupdate.  PerfMark may need to disable some functionality, and thus may need to make some tracing
123*27e8546dSMatt Gilbridecalls become No-ops.  In such cases, it will remain safe to call these functions being recorded.
124*27e8546dSMatt Gilbride
125*27e8546dSMatt Gilbride## Users
126*27e8546dSMatt Gilbride
127*27e8546dSMatt GilbridePerfMark was designed originally for [gRPC](https://github.com/grpc/grpc-java). It is also used
128*27e8546dSMatt Gilbrideby [Zuul](https://github.com/Netflix/zuul).
129