CpuThreadStateDataSeries implements DataSeries<CpuProfilerStage.ThreadState> { @Override public List<SeriesData<CpuProfilerStage.ThreadState>> getDataForRange(Range rangeUs) { List<SeriesData<CpuProfilerStage.ThreadState>> series = new ArrayList<>(); long minNs = TimeUnit.MICROSECONDS.toNanos((long)rangeUs.getMin()); long maxNs = TimeUnit.MICROSECONDS.toNanos((long)rangeUs.getMax()); GetEventGroupsResponse response = myClient.getEventGroups( GetEventGroupsRequest.newBuilder() .setStreamId(myStreamId) .setPid(myPid) .setKind(Common.Event.Kind.CPU_THREAD) .setGroupId(myThreadId) .setFromTimestamp(minNs) .setToTimestamp(maxNs) .build()); assert response.getGroupsCount() <= 1; if (response.getGroupsCount() == 1) { ArrayList<Double> captureTimes = new ArrayList<>(2); if (mySelectedCapture != null && mySelectedCapture.getThreads().stream().anyMatch(t -> t.getId() == myThreadId)) { captureTimes.add(mySelectedCapture.getRange().getMin()); captureTimes.add(mySelectedCapture.getRange().getMax()); } int i = 0; int j = 0; boolean inCapture = false; Cpu.CpuThreadData.State state = Cpu.CpuThreadData.State.UNSPECIFIED; List<Common.Event> events = response.getGroups(0).getEventsList(); while (i < events.size()) { Common.Event event = events.get(i); long timestamp = TimeUnit.NANOSECONDS.toMicros(event.getTimestamp()); long captureTime = j < captureTimes.size() ? captureTimes.get(j).longValue() : Long.MAX_VALUE; long time; if (captureTime < timestamp) { inCapture = !inCapture; time = captureTime; j++; } else { state = event.getCpuThread().getState(); time = timestamp; i++; } if (state != Cpu.CpuThreadData.State.UNSPECIFIED) { series.add(new SeriesData<>(time, CpuThreadsModel.getState(state, inCapture))); } } while (j < captureTimes.size()) { inCapture = !inCapture; series.add(new SeriesData<>(captureTimes.get(j).longValue(), CpuThreadsModel.getState(state, inCapture))); j++; } } return series; } CpuThreadStateDataSeries(@NotNull TransportServiceGrpc.TransportServiceBlockingStub client,
                                  long streamId,
                                  int pid,
                                  int threadId,
                                  @Nullable CpuCapture selectedCapture); @Override List<SeriesData<CpuProfilerStage.ThreadState>> getDataForRange(Range rangeUs);  }
@Test public void emptyRange() { DataSeries<CpuProfilerStage.ThreadState> series = createThreadSeries(10); List<SeriesData<CpuProfilerStage.ThreadState>> dataSeries = series.getDataForRange(new Range()); assertNotNull(dataSeries); assertTrue(dataSeries.isEmpty()); }
@Test public void nonEmptyRange() { Range range = new Range(TimeUnit.SECONDS.toMicros(1), TimeUnit.SECONDS.toMicros(15)); DataSeries<CpuProfilerStage.ThreadState> series = createThreadSeries(2); List<SeriesData<CpuProfilerStage.ThreadState>> dataSeries = series.getDataForRange(range); assertNotNull(dataSeries); assertEquals(5, dataSeries.size()); assertEquals(CpuProfilerStage.ThreadState.RUNNING, dataSeries.get(0).value); assertEquals(CpuProfilerStage.ThreadState.UNKNOWN, dataSeries.get(1).value); assertEquals(CpuProfilerStage.ThreadState.SLEEPING, dataSeries.get(2).value); assertEquals(CpuProfilerStage.ThreadState.WAITING, dataSeries.get(3).value); assertEquals(CpuProfilerStage.ThreadState.DEAD, dataSeries.get(4).value); }
@Test public void nonEmptyRangeWithFakeTraceSuccessStatus() throws Exception { Assume.assumeFalse(myIsUnifiedPipeline); CpuProfilerTestUtils.captureSuccessfully(myProfilerStage, myService, myTransportService, CpuProfilerTestUtils.readValidTrace()); CpuCapture capture = myProfilerStage.getCapture(); assertNotNull(capture); int tid = capture.getMainThreadId(); DataSeries<CpuProfilerStage.ThreadState> series = createThreadSeries(tid); myService.addThreads(tid, "main", Arrays.asList( CpuProfiler.GetThreadsResponse.ThreadActivity.newBuilder() .setTimestamp(TimeUnit.MICROSECONDS.toNanos((long)capture.getRange().getMin()) - TimeUnit.SECONDS.toNanos(2)) .setNewState(Cpu.CpuThreadData.State.RUNNING).build(), CpuProfiler.GetThreadsResponse.ThreadActivity.newBuilder() .setTimestamp(TimeUnit.MICROSECONDS.toNanos((long)capture.getRange().getMax()) - TimeUnit.SECONDS.toNanos(2)) .setNewState(Cpu.CpuThreadData.State.SLEEPING).build())); List<SeriesData<CpuProfilerStage.ThreadState>> dataSeries = series.getDataForRange(new Range(Long.MIN_VALUE, Long.MAX_VALUE)); assertNotNull(dataSeries); assertEquals(4, dataSeries.size()); assertEquals(CpuProfilerStage.ThreadState.RUNNING, dataSeries.get(0).value); assertEquals(CpuProfilerStage.ThreadState.RUNNING_CAPTURED, dataSeries.get(1).value); assertEquals(CpuProfilerStage.ThreadState.SLEEPING_CAPTURED, dataSeries.get(2).value); assertEquals(CpuProfilerStage.ThreadState.SLEEPING, dataSeries.get(3).value); }
@Test public void captureBeforeFirstActivity() throws Exception { Assume.assumeFalse(myIsUnifiedPipeline); CpuProfilerTestUtils.captureSuccessfully(myProfilerStage, myService, myTransportService, CpuProfilerTestUtils.readValidTrace()); CpuCapture capture = myProfilerStage.getCapture(); assertNotNull(capture); int tid = capture.getMainThreadId(); DataSeries<CpuProfilerStage.ThreadState> series = createThreadSeries(tid); myService.addThreads(tid, "main", Arrays.asList( CpuProfiler.GetThreadsResponse.ThreadActivity.newBuilder() .setTimestamp(TimeUnit.MICROSECONDS.toNanos((long)capture.getRange().getMin()) + TimeUnit.SECONDS.toNanos(1)) .setNewState(Cpu.CpuThreadData.State.RUNNING).build(), CpuProfiler.GetThreadsResponse.ThreadActivity.newBuilder() .setTimestamp(TimeUnit.MICROSECONDS.toNanos((long)capture.getRange().getMin()) + TimeUnit.SECONDS.toNanos(2)) .setNewState(Cpu.CpuThreadData.State.SLEEPING).build())); List<SeriesData<CpuProfilerStage.ThreadState>> dataSeries = series.getDataForRange(new Range(Long.MIN_VALUE, Long.MAX_VALUE)); assertNotNull(dataSeries); assertEquals(3, dataSeries.size()); assertEquals(CpuProfilerStage.ThreadState.RUNNING_CAPTURED, dataSeries.get(0).value); assertEquals(CpuProfilerStage.ThreadState.SLEEPING_CAPTURED, dataSeries.get(1).value); assertEquals(CpuProfilerStage.ThreadState.SLEEPING, dataSeries.get(2).value); }