Skip to content

Commit

Permalink
Counter selection UI.
Browse files Browse the repository at this point in the history
  • Loading branch information
pmuetschard committed Jun 11, 2019
1 parent db7933a commit 6d3c07a
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 2 deletions.
117 changes: 117 additions & 0 deletions gapic/src/main/com/google/gapid/perfetto/models/CounterTrack.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@
import static java.lang.String.format;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.gapid.perfetto.TimeSpan;
import com.google.gapid.perfetto.views.CountersSelectionView;
import com.google.gapid.perfetto.views.State;

import org.eclipse.swt.widgets.Composite;

import java.util.Arrays;

public class CounterTrack extends Track<CounterTrack.Data> {
private static final String VIEW_SQL =
Expand All @@ -33,6 +40,9 @@ public class CounterTrack extends Track<CounterTrack.Data> {
private static final String SUMMARY_SQL =
"select min(ts), max(ts + dur), avg(value) from %s group by quantum_ts";
private static final String COUNTER_SQL = "select ts, ts + dur, value from %s";
private static final String RANGE_SQL =
"select ts, ts + dur, value from %s " +
"where ts + dur >= %d and ts <= %d order by ts";

private final long id;
private final double min;
Expand Down Expand Up @@ -99,6 +109,22 @@ private String counterSQL() {
return format(COUNTER_SQL, tableName("span"));
}

public ListenableFuture<Data> getValues(QueryEngine qe, TimeSpan ts) {
return transform(qe.query(rangeSql(ts)), res -> {
int rows = res.getNumRows();
Data data = new Data(null, new long[rows], new double[rows]);
res.forEachRow((i, r) -> {
data.ts[i] = r.getLong(0);
data.values[i] = r.getDouble(2);
});
return data;
});
}

private String rangeSql(TimeSpan ts) {
return format(RANGE_SQL, tableName("vals"), ts.start, ts.end);
}

public static class Data extends Track.Data {
public final long[] ts;
public final double[] values;
Expand All @@ -109,4 +135,95 @@ public Data(DataRequest request, long[] ts, double[] values) {
this.values = values;
}
}

public static class Values implements Selection, Selection.CombiningBuilder.Combinable<Values> {
public final long[] ts;
public final String[] names;
public final double[][] values;

public Values(String name, Data data) {
this.ts = data.ts;
this.names = new String[] { name };
this.values = new double[][] { data.values };
}

private Values(long[] ts, String[] names, double[][] values) {
this.ts = ts;
this.names = names;
this.values = values;
}

@Override
public String getTitle() {
return "Counters";
}

@Override
public Composite buildUi(Composite parent, State state) {
return new CountersSelectionView(parent, state, this);
}

@Override
public Values combine(Values other) {
long[] newTs = combineTs(ts, other.ts);

double[][] newValues = new double[names.length + other.names.length][newTs.length];
for (int i = 0, me = 0, them = 0; i < newTs.length; i++) {
long rTs = newTs[i], meTs = ts[me], themTs = other.ts[them];
if (rTs == meTs) {
for (int n = 0; n < names.length; n++) {
newValues[n][i] = values[n][me];
}
me = Math.min(me + 1, ts.length - 1);
} else if (i > 0) {
for (int n = 0; n < names.length; n++) {
newValues[n][i] = newValues[n][i - 1];
}
}

if (rTs == themTs) {
for (int n = 0; n < other.names.length; n++) {
newValues[n + names.length][i] = other.values[n][them];
}
them = Math.min(them + 1, other.ts.length - 1);
} else if (i > 0) {
for (int n = 0; n < other.names.length; n++) {
newValues[names.length + n][i] = newValues[names.length + n][i - 1];
}
}
}

String[] newNames = Arrays.copyOf(names, names.length + other.names.length);
System.arraycopy(other.names, 0, newNames, names.length, other.names.length);
return new Values(newTs, newNames, newValues);
}

private static long[] combineTs(long[] a, long[] b) {
long[] r = new long[a.length + b.length];
int ai = 0, bi = 0, ri = 0;
for (; ai < a.length && bi < b.length; ri++) {
long av = a[ai], bv = b[bi];
if (av == bv) {
r[ri] = av;
ai++;
bi++;
} else if (av < bv) {
r[ri] = av;
ai++;
} else {
r[ri] = bv;
bi++;
}
}
// One of these copies does nothing.
System.arraycopy(a, ai, r, ri, a.length - ai);
System.arraycopy(b, bi, r, ri, b.length - bi);
return Arrays.copyOf(r, ri + a.length - ai + b.length - bi); // Truncate array.
}

@Override
public Selection build() {
return this;
}
}
}
11 changes: 10 additions & 1 deletion gapic/src/main/com/google/gapid/perfetto/views/CounterPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@

import static com.google.gapid.perfetto.views.Loading.drawLoading;
import static com.google.gapid.perfetto.views.StyleConstants.colors;
import static com.google.gapid.util.MoreFutures.transform;

import com.google.gapid.perfetto.TimeSpan;
import com.google.gapid.perfetto.canvas.Area;
import com.google.gapid.perfetto.canvas.RenderContext;
import com.google.gapid.perfetto.canvas.Size;
import com.google.gapid.perfetto.models.CounterTrack;
import com.google.gapid.perfetto.models.Selection.CombiningBuilder;

public class CounterPanel extends TrackPanel {
public class CounterPanel extends TrackPanel implements Selectable {
private static final double HEIGHT = 30;
private static final double HOVER_MARGIN = 10;
private static final double HOVER_PADDING = 4;
Expand Down Expand Up @@ -123,6 +126,12 @@ public void stop() {
};
}

@Override
public void computeSelection(CombiningBuilder builder, Area area, TimeSpan ts) {
builder.add(Kind.Counter, transform(
track.getValues(state.getQueryEngine(), ts), data -> new CounterTrack.Values(name, data)));
}

private static class HoverCard {
public final double value;
public final String label;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (C) 2019 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gapid.perfetto.views;

import static com.google.gapid.perfetto.TimeSpan.timeToString;
import static com.google.gapid.widgets.Widgets.createTableColumn;
import static com.google.gapid.widgets.Widgets.createTableViewer;
import static com.google.gapid.widgets.Widgets.packColumns;

import com.google.gapid.perfetto.models.CounterTrack;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;

public class CountersSelectionView extends Composite {
public CountersSelectionView(Composite parent, State state, CounterTrack.Values sel) {
super(parent, SWT.None);
setLayout(new FillLayout());

TableViewer viewer = createTableViewer(this, SWT.NONE);
viewer.setContentProvider(new ArrayContentProvider());
viewer.setLabelProvider(new LabelProvider());

createTableColumn(
viewer, "Time", r -> timeToString(sel.ts[(Integer)r] - state.getTraceTime().start));
for (int i = 0; i < sel.names.length; i++) {
final int idx = i;
createTableColumn(viewer, sel.names[i], r -> String.valueOf(sel.values[idx][(Integer)r]));
}

Integer[] rows = new Integer[sel.ts.length];
for (int i = 0; i < rows.length; i++) {
rows[i] = i;
}
viewer.setInput(rows);
packColumns(viewer.getTable());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ public interface Selectable {

public static enum Kind {
// Order as shown in the UI.
Thread, ThreadState, Cpu;
Thread, ThreadState, Cpu, Counter;
}
}

0 comments on commit 6d3c07a

Please sign in to comment.