public class ThreadLogVisualizer {
// Do not show tasks shorter than 5ms
- final public static long DISCARD_LIMIT = 0;
+ final public static long DISCARD_LIMIT = 2 * 1000 * 1000;
// 1s columns
final public static long COLUMN_WIDTH = 1000000000;
+ final int onlyOneThread = -1;
+
+ final String colors[] = {
+ "#53c0a7",
+ "#ca49a1",
+ "#64b74e",
+ "#a159ca",
+ "#b6b345",
+ "#656bc5",
+ "#da943b",
+ "#5e99d3",
+ "#d1592b",
+ "#418a53",
+ "#e16182",
+ "#777d34",
+ "#ca89ca",
+ "#b7754c",
+ "#9e4b6b",
+ "#cb4347"
+ };
+
class Task implements Comparable<Task> {
String name;
long beginTime;
long endTime;
long threadId;
+ long combined = 0;
public Task(String name, long threadId, long beginTime, long endTime) {
+ if(name.length() > 100) name = name.substring(0, 99);
this.name = name;
this.threadId = threadId;
this.beginTime = beginTime;
ArrayList<Task> tasks = new ArrayList<Task>();
+ private boolean acceptThread(long threadId) {
+ if(onlyOneThread == -1) return true;
+ else return (threadId&15) == onlyOneThread;
+ }
+
+ private Map<Long, Task> compositeTasks = new HashMap<>();
+
public void read(DataInput input) {
try {
while(true) {
try {
- String taskName = input.readUTF();
+ String taskName = input.readUTF();
long threadId = input.readLong();
long beginTime = input.readLong();
long endTime = input.readLong();
- if((endTime-beginTime) > DISCARD_LIMIT)
- tasks.add(new Task(taskName, threadId, beginTime, endTime));
+ if(!acceptThread(threadId)) continue;
+ if((endTime-beginTime) > DISCARD_LIMIT) {
+ tasks.add(new Task(taskName, threadId, beginTime, endTime));
+ Task t = compositeTasks.remove(threadId);
+ if(t != null) {
+ if((t.endTime-t.beginTime) > DISCARD_LIMIT) {
+ tasks.add(new Task(t.combined + " small tasks", t.threadId, t.beginTime, t.endTime));
+ }
+ }
+ } else {
+ Task t = compositeTasks.get(threadId);
+ if(t == null) {
+ t = new Task("", threadId, beginTime, endTime);
+ compositeTasks.put(threadId, t);
+ }
+ if(beginTime - t.endTime > DISCARD_LIMIT) {
+ tasks.add(new Task(t.combined + " small tasks", t.threadId, t.beginTime, t.endTime));
+ t = new Task("", threadId, beginTime, endTime);
+ compositeTasks.put(threadId, t);
+ }
+ t.endTime = endTime;
+ t.combined++;
+ if((t.endTime-t.beginTime) > DISCARD_LIMIT) {
+ tasks.add(new Task(t.combined + " small tasks", t.threadId, t.beginTime, t.endTime));
+ compositeTasks.remove(threadId);
+ }
+ }
} catch(EOFException e) {
break;
}
(task.beginTime-minTime)*timeScale,
(r+1)*rowHeight);
s.printf(locale,
- "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"green\"/>\n",
+ "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"" + colors[(int)task.threadId & 15] + "\"/>\n",
(task.beginTime-minTime)*timeScale,
r*rowHeight,
(task.endTime-task.beginTime)*timeScale,
rowHeight);
}
for(Task task : lane.tasks) {
+ int time = (int)(1e-6 * (task.endTime-task.beginTime));
s.printf(locale,
"<text x=\"%f\" y=\"%f\">%s</text>\n",
(task.endTime-minTime)*timeScale,
(r+0.8)*rowHeight,
- task.name);
+ Integer.toString(time) + "ms: " + task.name);
}
}
s.println("</svg>");
(task.beginTime-minTime)*timeScale,
(r+1)*rowHeight);
s.printf(locale,
- "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"green\"/>\n",
+ "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"" + colors[(int)task.threadId & 15] + "\"/>\n",
(task.beginTime-minTime)*timeScale,
r*rowHeight,
(task.endTime-task.beginTime)*timeScale,
(task.beginTime-minTime)*timeScale,
(r+1)*rowHeight);
s.printf(locale,
- "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"green\"/>\n",
+ "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"" + colors[(int)task.threadId & 15] + "\"/>\n",
(task.beginTime-minTime)*timeScale,
r*rowHeight,
(task.endTime-task.beginTime)*timeScale,