• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.java6;
18 
19 import io.perfmark.impl.Generator;
20 import io.perfmark.impl.Mark;
21 import io.perfmark.impl.MarkHolder;
22 import java.util.AbstractCollection;
23 import java.util.ArrayDeque;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.Deque;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Queue;
31 
32 final class SynchronizedMarkHolder extends MarkHolder {
33   private static final long GEN_MASK = (1 << Generator.GEN_OFFSET) - 1;
34 
35   private static final long START_N1S1_OP = Mark.Operation.TASK_START_N1S1.ordinal();
36   private static final long START_N1S2_OP = Mark.Operation.TASK_START_N1S2.ordinal();
37   private static final long STOP_N1S0_OP = Mark.Operation.TASK_END_N1S0.ordinal();
38   private static final long STOP_N1S1_OP = Mark.Operation.TASK_END_N1S1.ordinal();
39   private static final long STOP_N1S2_OP = Mark.Operation.TASK_END_N1S2.ordinal();
40   private static final long EVENT_N1S1_OP = Mark.Operation.EVENT_N1S1.ordinal();
41   private static final long EVENT_N1S2_OP = Mark.Operation.EVENT_N1S2.ordinal();
42   private static final long EVENT_N2S2_OP = Mark.Operation.EVENT_N2S2.ordinal();
43   private static final long LINK_OP = Mark.Operation.LINK.ordinal();
44   private static final long TAG_N1S1_OP = Mark.Operation.TAG_N1S1.ordinal();
45   private static final long TAG_KEYED_N0S2_OP = Mark.Operation.TAG_KEYED_N0S2.ordinal();
46   private static final long TAG_KEYED_N1S1_OP = Mark.Operation.TAG_KEYED_N1S1.ordinal();
47   private static final long TAG_KEYED_N2S1_OP = Mark.Operation.TAG_KEYED_N2S1.ordinal();
48 
49   private final int maxEvents;
50   private final long maxEventsMask;
51 
52   // where to write to next
53   private long nIdx;
54   private long sIdx;
55 
56   private final long[] nums;
57   private final String[] strings;
58 
SynchronizedMarkHolder()59   SynchronizedMarkHolder() {
60     this(32768);
61   }
62 
SynchronizedMarkHolder(int maxEvents)63   SynchronizedMarkHolder(int maxEvents) {
64     if (((maxEvents - 1) & maxEvents) != 0) {
65       throw new IllegalArgumentException(maxEvents + " is not a power of two");
66     }
67     if (maxEvents <= 0) {
68       throw new IllegalArgumentException(maxEvents + " is not positive");
69     }
70     this.maxEvents = maxEvents;
71     this.maxEventsMask = maxEvents - 1L;
72     this.nums = new long[maxEvents];
73     this.strings = new String[maxEvents];
74   }
75 
writeNnss(long genOp, long n0, long n1, String s0, String s1)76   private void writeNnss(long genOp, long n0, long n1, String s0, String s1) {
77     nums[(int) (nIdx++ & maxEventsMask)] = n0;
78     nums[(int) (nIdx++ & maxEventsMask)] = n1;
79     strings[(int) (sIdx++ & maxEventsMask)] = s0;
80     strings[(int) (sIdx++ & maxEventsMask)] = s1;
81     nums[(int) (nIdx++ & maxEventsMask)] = genOp;
82   }
83 
writeNss(long genOp, long n0, String s0, String s1)84   private void writeNss(long genOp, long n0, String s0, String s1) {
85     nums[(int) (nIdx++ & maxEventsMask)] = n0;
86     strings[(int) (sIdx++ & maxEventsMask)] = s0;
87     strings[(int) (sIdx++ & maxEventsMask)] = s1;
88     nums[(int) (nIdx++ & maxEventsMask)] = genOp;
89   }
90 
writeNs(long genOp, long n0, String s0)91   private void writeNs(long genOp, long n0, String s0) {
92     nums[(int) (nIdx++ & maxEventsMask)] = n0;
93     strings[(int) (sIdx++ & maxEventsMask)] = s0;
94     nums[(int) (nIdx++ & maxEventsMask)] = genOp;
95   }
96 
writeN(long genOp, long n0)97   private void writeN(long genOp, long n0) {
98     nums[(int) (nIdx++ & maxEventsMask)] = n0;
99     nums[(int) (nIdx++ & maxEventsMask)] = genOp;
100   }
101 
writeNns(long genOp, long n0, long n1, String s0)102   private void writeNns(long genOp, long n0, long n1, String s0) {
103     nums[(int) (nIdx++ & maxEventsMask)] = n0;
104     nums[(int) (nIdx++ & maxEventsMask)] = n1;
105     strings[(int) (sIdx++ & maxEventsMask)] = s0;
106     nums[(int) (nIdx++ & maxEventsMask)] = genOp;
107   }
108 
writeSs(long genOp, String s0, String s1)109   private void writeSs(long genOp, String s0, String s1) {
110     strings[(int) (sIdx++ & maxEventsMask)] = s0;
111     strings[(int) (sIdx++ & maxEventsMask)] = s1;
112     nums[(int) (nIdx++ & maxEventsMask)] = genOp;
113   }
114 
115   @Override
start( long gen, String taskName, String tagName, long tagId, long nanoTime)116   public synchronized void start(
117       long gen, String taskName, String tagName, long tagId, long nanoTime) {
118     writeNs(gen + START_N1S1_OP, nanoTime, taskName);
119     writeNs(gen + TAG_N1S1_OP, tagId, tagName);
120   }
121 
122   @Override
start(long gen, String taskName, long nanoTime)123   public synchronized void start(long gen, String taskName, long nanoTime) {
124     writeNs(gen + START_N1S1_OP, nanoTime, taskName);
125   }
126 
127   @Override
start(long gen, String taskName, String subTaskName, long nanoTime)128   public synchronized void start(long gen, String taskName, String subTaskName, long nanoTime) {
129     writeNss(gen + START_N1S2_OP, nanoTime, taskName, subTaskName);
130   }
131 
132   @Override
link(long gen, long linkId)133   public synchronized void link(long gen, long linkId) {
134     writeN(gen + LINK_OP, linkId);
135   }
136 
137   @Override
stop(long gen, long nanoTime)138   public synchronized void stop(long gen, long nanoTime) {
139     writeN(gen + STOP_N1S0_OP, nanoTime);
140   }
141 
142   @Override
stop( long gen, String taskName, String tagName, long tagId, long nanoTime)143   public synchronized void stop(
144       long gen, String taskName, String tagName, long tagId, long nanoTime) {
145     writeNs(gen + TAG_N1S1_OP, tagId, tagName);
146     writeNs(gen + STOP_N1S1_OP, nanoTime, taskName);
147   }
148 
149   @Override
stop(long gen, String taskName, long nanoTime)150   public synchronized void stop(long gen, String taskName, long nanoTime) {
151     writeNs(gen + STOP_N1S1_OP, nanoTime, taskName);
152   }
153 
154   @Override
stop(long gen, String taskName, String subTaskName, long nanoTime)155   public synchronized void stop(long gen, String taskName, String subTaskName, long nanoTime) {
156     writeNss(gen + STOP_N1S2_OP, nanoTime, taskName, subTaskName);
157   }
158 
159   @Override
event( long gen, String eventName, String tagName, long tagId, long nanoTime)160   public synchronized void event(
161       long gen, String eventName, String tagName, long tagId, long nanoTime) {
162     writeNnss(gen + EVENT_N2S2_OP, nanoTime, tagId, eventName, tagName);
163   }
164 
165   @Override
event(long gen, String eventName, long nanoTime)166   public synchronized void event(long gen, String eventName, long nanoTime) {
167     writeNs(gen + EVENT_N1S1_OP, nanoTime, eventName);
168   }
169 
170   @Override
event(long gen, String eventName, String subEventName, long nanoTime)171   public synchronized void event(long gen, String eventName, String subEventName, long nanoTime) {
172     writeNss(gen + EVENT_N1S2_OP, nanoTime, eventName, subEventName);
173   }
174 
175   @Override
attachTag(long gen, String tagName, long tagId)176   public synchronized void attachTag(long gen, String tagName, long tagId) {
177     writeNs(gen + TAG_N1S1_OP, tagId, tagName);
178   }
179 
180   @Override
attachKeyedTag(long gen, String name, long value0)181   public synchronized void attachKeyedTag(long gen, String name, long value0) {
182     writeNs(gen + TAG_KEYED_N1S1_OP, value0, name);
183   }
184 
185   @Override
attachKeyedTag(long gen, String name, String value)186   public synchronized void attachKeyedTag(long gen, String name, String value) {
187     writeSs(gen + TAG_KEYED_N0S2_OP, name, value);
188   }
189 
190   @Override
attachKeyedTag(long gen, String name, long value0, long value1)191   public synchronized void attachKeyedTag(long gen, String name, long value0, long value1) {
192     writeNns(gen + TAG_KEYED_N2S1_OP, value0, value1, name);
193   }
194 
195   @Override
resetForTest()196   public synchronized void resetForTest() {
197     Arrays.fill(nums, 0);
198     Arrays.fill(strings, null);
199     nIdx = 0;
200     sIdx = 0;
201   }
202 
203   @Override
read(boolean concurrentWrites)204   public List<Mark> read(boolean concurrentWrites) {
205     Kyoo<Long> numQ;
206     Kyoo<String> stringQ;
207     {
208       final long[] nums = new long[maxEvents];
209       final String[] strings = new String[maxEvents];
210       final long nIdx;
211       final long sIdx;
212 
213       synchronized (this) {
214         System.arraycopy(this.nums, 0, nums, 0, maxEvents);
215         System.arraycopy(this.strings, 0, strings, 0, maxEvents);
216         nIdx = this.nIdx;
217         sIdx = this.sIdx;
218       }
219       Long[] numsBoxed = new Long[nums.length];
220       for (int i = 0; i < nums.length; i++) {
221         numsBoxed[i] = nums[i];
222       }
223       numQ = new Kyoo<Long>(numsBoxed, nIdx, (int) Math.min(nIdx, maxEvents));
224       stringQ = new Kyoo<String>(strings, sIdx, (int) Math.min(sIdx, maxEvents));
225     }
226 
227     Deque<Mark> marks = new ArrayDeque<Mark>(maxEvents);
228 
229     while (true) {
230       if (numQ.isEmpty()) {
231         break;
232       }
233       long genOp = numQ.remove();
234       long gen = genOp & ~GEN_MASK;
235       Mark.Operation op = Mark.Operation.valueOf((int) (genOp & GEN_MASK));
236 
237       if (op.getNumbers() > numQ.size()
238           || op.getStrings() > stringQ.size()) {
239         break;
240       }
241       long n1;
242       String s1;
243       long n2;
244       String s2;
245       switch (op) {
246         case TASK_START_N1S1:
247           n1 = numQ.remove();
248           s1 = stringQ.remove();
249           marks.addFirst(Mark.taskStart(gen, n1, s1));
250           break;
251         case TASK_START_N1S2:
252           n1 = numQ.remove();
253           s2 = stringQ.remove();
254           s1 = stringQ.remove();
255           marks.addFirst(Mark.taskStart(gen, n1, s1, s2));
256           break;
257         case TASK_END_N1S0:
258           n1 = numQ.remove();
259           marks.addFirst(Mark.taskEnd(gen, n1));
260           break;
261         case TASK_END_N1S1:
262           n1 = numQ.remove();
263           s1 = stringQ.remove();
264           marks.addFirst(Mark.taskEnd(gen, n1, s1));
265           break;
266         case TASK_END_N1S2:
267           n1 = numQ.remove();
268           s2 = stringQ.remove();
269           s1 = stringQ.remove();
270           marks.addFirst(Mark.taskEnd(gen, n1, s1, s2));
271           break;
272         case EVENT_N1S1:
273           n1 = numQ.remove();
274           s1 = stringQ.remove();
275           marks.addFirst(Mark.event(gen, n1, s1));
276           break;
277         case EVENT_N1S2:
278           n1 = numQ.remove();
279           s2 = stringQ.remove();
280           s1 = stringQ.remove();
281           marks.addFirst(Mark.event(gen, n1, s1, s2));
282           break;
283         case EVENT_N2S2:
284           n2 = numQ.remove();
285           s2 = stringQ.remove();
286           n1 = numQ.remove();
287           s1 = stringQ.remove();
288           marks.addFirst(Mark.event(gen, n1, s1, s2, n2));
289           break;
290         case EVENT_N2S3:
291           throw new UnsupportedOperationException();
292         case LINK:
293           n1 = numQ.remove();
294           marks.addFirst(Mark.link(gen, n1));
295           break;
296         case TAG_N0S1:
297           throw new UnsupportedOperationException();
298         case TAG_N1S0:
299           throw new UnsupportedOperationException();
300         case TAG_N1S1:
301           n1 = numQ.remove();
302           s1 = stringQ.remove();
303           marks.addFirst(Mark.tag(gen, s1, n1));
304           break;
305         case TAG_KEYED_N0S2:
306           s2 = stringQ.remove();
307           s1 = stringQ.remove();
308           marks.addFirst(Mark.keyedTag(gen, s1, s2));
309           break;
310         case TAG_KEYED_N1S1:
311           n1 = numQ.remove();
312           s1 = stringQ.remove();
313           marks.addFirst(Mark.keyedTag(gen, s1, n1));
314           break;
315         case TAG_KEYED_N2S1:
316           n2 = numQ.remove();
317           n1 = numQ.remove();
318           s1 = stringQ.remove();
319           marks.addFirst(Mark.keyedTag(gen, s1, n1, n2));
320           break;
321         case NONE:
322           throw new UnsupportedOperationException();
323       }
324     }
325 
326     return Collections.unmodifiableList(new ArrayList<Mark>(marks));
327   }
328 
329   @Override
maxMarks()330   public int maxMarks() {
331     return maxEvents;
332   }
333 
334   private final class Kyoo<T> extends AbstractCollection<T> implements Queue<T> {
335 
336     private final T[] elements;
337     private final long wIdx;
338     private final int size;
339 
340     private int ri;
341 
Kyoo(T[] elements, long wIdx, int size)342     Kyoo(T[] elements, long wIdx, int size) {
343       this.elements = elements;
344       this.wIdx = wIdx;
345       this.size = size;
346     }
347 
348     @Override
iterator()349     public Iterator<T> iterator() {
350       throw new UnsupportedOperationException();
351     }
352 
353     @Override
size()354     public int size() {
355       return size - ri;
356     }
357 
358     @Override
offer(T t)359     public boolean offer(T t) {
360       throw new UnsupportedOperationException();
361     }
362 
363     @Override
remove()364     public T remove() {
365       checkSize();
366       return poll();
367     }
368 
369     @Override
poll()370     public T poll() {
371       if (size() == 0) {
372         return null;
373       }
374       int rIdx = (int) (((wIdx - 1) - ri++) & maxEventsMask);
375       return elements[rIdx];
376     }
377 
378     @Override
element()379     public T element() {
380       checkSize();
381       return peek();
382     }
383 
384     @Override
peek()385     public T peek() {
386       if (size() == 0) {
387         return null;
388       }
389       int rIdx = (int) (((wIdx - 1) - ri) & maxEventsMask);
390       return elements[rIdx];
391     }
392 
checkSize()393     private void checkSize() {
394       if (size() == 0) {
395         throw new IllegalStateException();
396       }
397     }
398   }
399 }
400