xref: /aosp_15_r20/external/perfmark/impl/src/main/java/io/perfmark/impl/Mark.java (revision 27e8546d0ef5f99cf83d5252272c7dd38d18d29a)
1 /*
2  * Copyright 2019 Google LLC
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package io.perfmark.impl;
18 
19 import java.util.Arrays;
20 import javax.annotation.Nullable;
21 
22 public final class Mark {
23   // TODO: make sure these match the values in Impl
24   public static final String NO_TAG_NAME = "";
25   public static final long NO_TAG_ID = Long.MIN_VALUE;
26   public static final long NO_LINK_ID = Long.MIN_VALUE;
27 
28   public static final long NO_NANOTIME = 0;
29 
30   private static final long N0 = 0;
31   private static final String S0 = null;
32 
33   private final long generation;
34 
35   private final long n1;
36   private final long n2;
37   private final long n3;
38 
39   @Nullable private final String s1;
40   @Nullable private final String s2;
41   @Nullable private final String s3;
42 
43   private final Operation operation;
44 
taskStart(long generation, long nanoTime, String name)45   public static Mark taskStart(long generation, long nanoTime, String name) {
46     return new Mark(nanoTime, N0, N0, name, S0, S0, generation, Operation.TASK_START_N1S1);
47   }
48 
taskStart(long generation, long nanoTime, String name, String subName)49   public static Mark taskStart(long generation, long nanoTime, String name, String subName) {
50     return new Mark(nanoTime, N0, N0, name, subName, S0, generation, Operation.TASK_START_N1S2);
51   }
52 
taskEnd(long generation, long nanoTime)53   public static Mark taskEnd(long generation, long nanoTime) {
54     return new Mark(nanoTime, N0, N0, S0, S0, S0, generation, Operation.TASK_END_N1S0);
55   }
56 
taskEnd(long generation, long nanoTime, String name)57   public static Mark taskEnd(long generation, long nanoTime, String name) {
58     return new Mark(nanoTime, N0, N0, name, S0, S0, generation, Operation.TASK_END_N1S1);
59   }
60 
taskEnd(long generation, long nanoTime, String name, String subName)61   public static Mark taskEnd(long generation, long nanoTime, String name, String subName) {
62     return new Mark(nanoTime, N0, N0, name, subName, S0, generation, Operation.TASK_END_N1S2);
63   }
64 
event(long generation, long nanoTime, String name)65   public static Mark event(long generation, long nanoTime, String name) {
66     return new Mark(nanoTime, N0, N0, name, S0, S0, generation, Operation.EVENT_N1S1);
67   }
68 
event(long generation, long nanoTime, String name, String subName)69   public static Mark event(long generation, long nanoTime, String name, String subName) {
70     return new Mark(nanoTime, N0, N0, name, subName, S0, generation, Operation.EVENT_N1S2);
71   }
72 
event( long generation, long nanoTime, String taskName, String tagName, long tagId)73   public static Mark event(
74       long generation, long nanoTime, String taskName, String tagName, long tagId) {
75     return new Mark(
76         nanoTime, tagId, N0, taskName, tagName, S0, generation, Operation.EVENT_N2S2);
77   }
78 
event( long generation, long nanoTime, String taskName, String subTaskName, String tagName, long tagId)79   public static Mark event(
80       long generation,
81       long nanoTime,
82       String taskName,
83       String subTaskName,
84       String tagName,
85       long tagId) {
86     return new Mark(
87         nanoTime, tagId, N0, taskName, subTaskName, tagName, generation, Operation.EVENT_N2S3);
88   }
89 
tag(long generation, String tagName, long tagId)90   public static Mark tag(long generation, String tagName, long tagId) {
91     return new Mark(tagId, N0, N0, tagName, S0, S0, generation, Operation.TAG_N1S1);
92   }
93 
tag(long generation, long tagId)94   public static Mark tag(long generation, long tagId) {
95     return new Mark(tagId, N0, N0, S0, S0, S0, generation, Operation.TAG_N1S0);
96   }
97 
tag(long generation, String tagName)98   public static Mark tag(long generation, String tagName) {
99     return new Mark(N0, N0, N0, tagName, S0, S0, generation, Operation.TAG_N0S1);
100   }
101 
keyedTag(long generation, String tagName, String value)102   public static Mark keyedTag(long generation, String tagName, String value) {
103     return new Mark(N0, N0, N0, tagName, value, S0, generation, Operation.TAG_KEYED_N0S2);
104   }
105 
keyedTag(long generation, String tagName, long value)106   public static Mark keyedTag(long generation, String tagName, long value) {
107     return new Mark(value, N0, N0, tagName, S0, S0, generation, Operation.TAG_KEYED_N1S1);
108   }
109 
keyedTag(long generation, String tagName, long value0, long value1)110   public static Mark keyedTag(long generation, String tagName, long value0, long value1) {
111     return new Mark(value0, value1, N0, tagName, S0, S0, generation, Operation.TAG_KEYED_N2S1);
112   }
113 
link(long generation, long linkId)114   public static Mark link(long generation, long linkId) {
115     return new Mark(linkId, N0, N0, S0, S0, S0, generation, Operation.LINK);
116   }
117 
withTaskName(String name)118   public Mark withTaskName(String name) {
119     switch (operation) {
120       case EVENT_N1S1:
121       case TASK_END_N1S1:
122       case TASK_START_N1S1:
123         return new Mark(n1, n2, n3, name, s2, s3, generation, operation);
124       case TASK_START_N1S2:
125       case TASK_END_N1S0:
126       case NONE:
127       case TASK_END_N1S2:
128       case EVENT_N1S2:
129       case EVENT_N2S2:
130       case EVENT_N2S3:
131       case LINK:
132       case TAG_N0S1:
133       case TAG_N1S0:
134       case TAG_N1S1:
135       case TAG_KEYED_N1S1:
136       case TAG_KEYED_N2S1:
137       case TAG_KEYED_N0S2:
138         throw new UnsupportedOperationException();
139     }
140     throw new AssertionError();
141   }
142 
Mark( long n1, long n2, long n3, @Nullable String s1, @Nullable String s2, @Nullable String s3, long generation, Operation operation)143   private Mark(
144       long n1,
145       long n2,
146       long n3,
147       @Nullable String s1,
148       @Nullable String s2,
149       @Nullable String s3,
150       long generation,
151       Operation operation) {
152     if (operation == null) {
153       throw new NullPointerException("operation");
154     }
155     this.operation = operation;
156     this.generation = generation;
157 
158     if (operation == Operation.NONE) {
159       throw new IllegalArgumentException("bad operation");
160     }
161     this.n1 = n1;
162     this.n2 = n2;
163     this.n3 = n3;
164 
165     this.s1 = s1;
166     this.s2 = s2;
167     this.s3 = s3;
168   }
169 
170   public enum OperationType {
171     NONE,
172     TASK_START,
173     TASK_END,
174     EVENT,
175     LINK,
176     TAG,
177     ;
178   }
179 
180   public enum Operation {
181     NONE(OperationType.NONE, 0, 0),
182     /** startTask(String taskName) 1 long for nanoTime. */
183     TASK_START_N1S1(OperationType.TASK_START, 1, 1),
184     /** startTask(String name, String subTaskName) 1 long for nanoTime. */
185     TASK_START_N1S2(OperationType.TASK_START, 1, 2),
186 
187     TASK_END_N1S0(OperationType.TASK_END, 1, 0),
188     TASK_END_N1S1(OperationType.TASK_END, 1, 1),
189     TASK_END_N1S2(OperationType.TASK_END, 1, 2),
190 
191     EVENT_N1S1(OperationType.EVENT, 1, 1),
192     EVENT_N1S2(OperationType.EVENT, 1, 2),
193     /** Tagged event, since attach tags can't apply to events */
194     EVENT_N2S2(OperationType.EVENT, 2, 2),
195     /** Tagged event, since attach tags can't apply to events */
196     EVENT_N2S3(OperationType.EVENT, 2, 3),
197 
198     LINK(OperationType.LINK, 1, 0),
199 
200     /** An unkeyed tag that has a single string value. */
201     TAG_N0S1(OperationType.TAG, 0, 1),
202     /** An unkeyed tag that has a single numeric value. */
203     TAG_N1S0(OperationType.TAG, 1, 0),
204     /**
205      * An unkeyed tag that has a string and numeric value. The values are unrelated to each other.
206      */
207     TAG_N1S1(OperationType.TAG, 1, 1),
208 
209     TAG_KEYED_N1S1(OperationType.TAG, 1, 1),
210 
211     TAG_KEYED_N2S1(OperationType.TAG, 2, 1),
212 
213     TAG_KEYED_N0S2(OperationType.TAG, 0, 2),
214     ;
215 
216     private final OperationType opType;
217     private final int longs;
218     private final int strings;
219 
Operation(OperationType opType, int longs, int strings)220     Operation(OperationType opType, int longs, int strings) {
221       this.opType = opType;
222       this.longs = longs;
223       this.strings = strings;
224       assert longs <= maxNumbers();
225       assert strings <= maxStrings();
226     }
227 
228     private static final Operation[] values = Operation.values();
229 
230     static {
231       assert values.length <= (1 << Generator.GEN_OFFSET);
232     }
233 
getOpType()234     public OperationType getOpType() {
235       return opType;
236     }
237 
getNumbers()238     public int getNumbers() {
239       return longs;
240     }
241 
getStrings()242     public int getStrings() {
243       return strings;
244     }
245 
maxNumbers()246     public static int maxNumbers() {
247       return 2;
248     }
249 
maxStrings()250     public static int maxStrings() {
251       return 3;
252     }
253 
maxMarkers()254     public static int maxMarkers() {
255       return 1;
256     }
257 
valueOf(int code)258     public static Operation valueOf(int code) {
259       return values[code];
260     }
261   }
262 
getNanoTime()263   public long getNanoTime() {
264     switch (operation.opType) {
265       case TASK_START:
266       case TASK_END:
267       case EVENT:
268         return n1;
269       case NONE:
270       case LINK:
271       case TAG:
272         throw new UnsupportedOperationException();
273     }
274     throw new AssertionError(operation.opType);
275   }
276 
getGeneration()277   public long getGeneration() {
278     return generation;
279   }
280 
getOperation()281   public Operation getOperation() {
282     return operation;
283   }
284 
getTagStringValue()285   public String getTagStringValue() {
286     switch (operation) {
287       case TAG_N0S1:
288       case TAG_N1S1:
289         return s1;
290       case TAG_KEYED_N0S2:
291       case EVENT_N2S2:
292         return s2;
293       case EVENT_N2S3:
294         return s3;
295       case TAG_N1S0:
296       case NONE:
297       case TASK_START_N1S1:
298       case TASK_START_N1S2:
299       case TASK_END_N1S0:
300       case TASK_END_N1S1:
301       case TASK_END_N1S2:
302       case EVENT_N1S1:
303       case EVENT_N1S2:
304       case TAG_KEYED_N1S1:
305       case TAG_KEYED_N2S1:
306       case LINK:
307         throw new UnsupportedOperationException();
308     }
309     throw new AssertionError(operation.opType);
310   }
311 
getTagFirstNumeric()312   public long getTagFirstNumeric() {
313     switch (operation) {
314       case TAG_N1S0:
315       case TAG_N1S1:
316       case TAG_KEYED_N1S1:
317       case TAG_KEYED_N2S1:
318         return n1;
319       case EVENT_N2S2:
320       case EVENT_N2S3:
321         return n2;
322       case TAG_N0S1:
323       case TAG_KEYED_N0S2:
324       case NONE:
325       case TASK_START_N1S1:
326       case TASK_START_N1S2:
327       case TASK_END_N1S0:
328       case TASK_END_N1S1:
329       case TASK_END_N1S2:
330       case EVENT_N1S1:
331       case EVENT_N1S2:
332       case LINK:
333         throw new UnsupportedOperationException();
334     }
335     throw new AssertionError(operation.opType);
336   }
337 
getTagSecondNumeric()338   public long getTagSecondNumeric() {
339     switch (operation) {
340       case TAG_KEYED_N2S1:
341         return n2;
342       case TAG_N1S0:
343       case TAG_N1S1:
344       case TAG_KEYED_N1S1:
345       case EVENT_N2S2:
346       case EVENT_N2S3:
347       case TAG_N0S1:
348       case TAG_KEYED_N0S2:
349       case NONE:
350       case TASK_START_N1S1:
351       case TASK_START_N1S2:
352       case TASK_END_N1S0:
353       case TASK_END_N1S1:
354       case TASK_END_N1S2:
355       case EVENT_N1S1:
356       case EVENT_N1S2:
357       case LINK:
358         throw new UnsupportedOperationException();
359     }
360     throw new AssertionError(operation.opType);
361   }
362 
getTagKey()363   public String getTagKey() {
364     switch (operation) {
365       case TAG_KEYED_N0S2:
366       case TAG_KEYED_N1S1:
367       case TAG_KEYED_N2S1:
368         return s1;
369       case TAG_N1S1:
370       case TAG_N0S1:
371       case TAG_N1S0:
372       case NONE:
373       case TASK_START_N1S1:
374       case TASK_START_N1S2:
375       case TASK_END_N1S0:
376       case TASK_END_N1S1:
377       case TASK_END_N1S2:
378       case EVENT_N1S1:
379       case EVENT_N1S2:
380       case EVENT_N2S2:
381       case EVENT_N2S3:
382       case LINK:
383         throw new UnsupportedOperationException();
384     }
385     throw new AssertionError(operation.opType);
386   }
387 
getTaskName()388   public String getTaskName() {
389     switch (operation) {
390       case TASK_START_N1S1:
391       case TASK_START_N1S2:
392       case TASK_END_N1S1:
393       case TASK_END_N1S2:
394       case EVENT_N1S1:
395       case EVENT_N1S2:
396       case EVENT_N2S2:
397       case EVENT_N2S3:
398         return s1;
399       case NONE:
400       case LINK:
401       case TASK_END_N1S0:
402       case TAG_N0S1:
403       case TAG_N1S0:
404       case TAG_N1S1:
405       case TAG_KEYED_N0S2:
406       case TAG_KEYED_N1S1:
407       case TAG_KEYED_N2S1:
408         throw new UnsupportedOperationException();
409     }
410     throw new AssertionError(operation);
411   }
412 
getSubTaskName()413   public String getSubTaskName() {
414     switch (operation) {
415       case TASK_END_N1S2:
416       case TASK_START_N1S2:
417       case EVENT_N1S2:
418       case EVENT_N2S3:
419         return s2;
420       case TASK_START_N1S1:
421       case TASK_END_N1S0:
422       case TASK_END_N1S1:
423       case EVENT_N1S1:
424       case EVENT_N2S2:
425       case NONE:
426       case LINK:
427       case TAG_N0S1:
428       case TAG_KEYED_N0S2:
429       case TAG_KEYED_N1S1:
430       case TAG_KEYED_N2S1:
431       case TAG_N1S0:
432       case TAG_N1S1:
433         throw new UnsupportedOperationException();
434     }
435     throw new AssertionError(operation);
436   }
437 
getLinkId()438   public long getLinkId() {
439     switch (operation.opType) {
440       case LINK:
441         return n1;
442       case TASK_START:
443       case TASK_END:
444       case EVENT:
445       case NONE:
446       case TAG:
447         throw new UnsupportedOperationException();
448     }
449     throw new AssertionError(operation.opType);
450   }
451 
452   @Override
equals(Object obj)453   public boolean equals(Object obj) {
454     if (!(obj instanceof Mark)) {
455       return false;
456     }
457     Mark that = (Mark) obj;
458     return equal(this.s1, that.s1)
459         && equal(this.s2, that.s2)
460         && equal(this.s3, that.s3)
461         && this.n1 == that.n1
462         && this.n2 == that.n2
463         && this.n3 == that.n3
464         && this.operation == that.operation
465         && this.generation == that.generation;
466   }
467 
468   @Override
hashCode()469   public int hashCode() {
470     return Arrays.hashCode(new Object[] {operation, s1, s2, s3, n1, n2, n3, generation});
471   }
472 
473   @Override
toString()474   public String toString() {
475     return "Mark{"
476         + "operation="
477         + operation
478         + ", "
479         + "s1="
480         + s1
481         + ", "
482         + "s2="
483         + s2
484         + ", "
485         + "s3="
486         + s3
487         + ", "
488         + "n1="
489         + n1
490         + ", "
491         + "n2="
492         + n2
493         + ", "
494         + "n3="
495         + n3
496         + ", "
497         + "generation="
498         + generation
499         + "}";
500   }
501 
equal(T a, T b)502   static <T> boolean equal(T a, T b) {
503     return a == b || a.equals(b);
504   }
505 }
506