--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.utils.threads.logger;\r
+\r
+import java.io.DataInput;\r
+import java.io.DataInputStream;\r
+import java.io.EOFException;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.PrintStream;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.Locale;\r
+import java.util.Map;\r
+\r
+public class ThreadLogVisualizer {\r
+ \r
+ // Do not show tasks shorter than 5ms\r
+ final public static long DISCARD_LIMIT = 0;\r
+ // 1s columns\r
+ final public static long COLUMN_WIDTH = 1000000000;\r
+ \r
+ class Task implements Comparable<Task> {\r
+ String name;\r
+ long beginTime;\r
+ long endTime;\r
+ long threadId;\r
+ \r
+ public Task(String name, long threadId, long beginTime, long endTime) {\r
+ this.name = name;\r
+ this.threadId = threadId;\r
+ this.beginTime = beginTime;\r
+ this.endTime = endTime;\r
+ }\r
+\r
+ @Override\r
+ // Differences will not fit into int\r
+ public int compareTo(Task o) {\r
+ if(beginTime > o.beginTime) return 1;\r
+ else if(beginTime == o.beginTime) return -1;\r
+ else return -1;\r
+ } \r
+ }\r
+ \r
+ ArrayList<Task> tasks = new ArrayList<Task>();\r
+ \r
+ public void read(DataInput input) {\r
+ try {\r
+ while(true) {\r
+ try {\r
+ String taskName = input.readUTF();\r
+ long threadId = input.readLong();\r
+ long beginTime = input.readLong();\r
+ long endTime = input.readLong();\r
+ if((endTime-beginTime) > DISCARD_LIMIT)\r
+ tasks.add(new Task(taskName, threadId, beginTime, endTime));\r
+ } catch(EOFException e) { \r
+ break;\r
+ }\r
+ } \r
+ } catch(IOException e) { \r
+ }\r
+ \r
+ Collections.sort(tasks);\r
+ }\r
+ \r
+ class Lane {\r
+ ArrayList<Task> tasks = new ArrayList<Task>();\r
+ long nextTime = 0;\r
+ }\r
+ \r
+ public void visualize3(PrintStream s) {\r
+ \r
+ long minTime = Long.MAX_VALUE;\r
+ long maxTime = Long.MIN_VALUE;\r
+ \r
+ ArrayList<Lane> lanes = new ArrayList<Lane>();\r
+ \r
+ int laneId = 0;\r
+ for(Task task : tasks) {\r
+\r
+ Lane lane;\r
+ \r
+ minTime = Math.min(minTime, task.beginTime);\r
+ maxTime = Math.max(maxTime, task.endTime);\r
+ \r
+ for(int seek = laneId-1; seek >= 0; --seek) {\r
+ if(lanes.get(seek).nextTime < task.beginTime) {\r
+ laneId = seek;\r
+ } else {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if(laneId < lanes.size())\r
+ lane = lanes.get(laneId);\r
+ else {\r
+ lane = new Lane();\r
+ lanes.add(lane);\r
+ }\r
+ \r
+ lane.tasks.add(task);\r
+ lane.nextTime = Math.max(task.endTime, task.beginTime+COLUMN_WIDTH);\r
+ System.out.println(task.name + " -> " + laneId + "[" + task.beginTime + "-" + task.endTime + "]");\r
+ \r
+ laneId++;\r
+ \r
+ }\r
+ \r
+ double timeScale = 1e-6;\r
+ double rowHeight = 30.0;\r
+ Locale locale = Locale.US;\r
+ int row = lanes.size();\r
+ \r
+ s.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");\r
+ s.println("<svg xmlns=\"http://www.w3.org/2000/svg\" overflow=\"visible\" version=\"1.1\">");\r
+ for(long time = minTime ; time < maxTime ; time += 1000000000) {\r
+ s.printf(locale,\r
+ "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"grey\"/>\n",\r
+ (time-minTime)*timeScale,\r
+ 0.0,\r
+ (time-minTime)*timeScale,\r
+ row*rowHeight);\r
+ } \r
+ for(int r = 0;r<lanes.size();++r) {\r
+ Lane lane = lanes.get(r);\r
+ for(Task task : lane.tasks) {\r
+ s.printf(locale,\r
+ "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\"/>\n",\r
+ (task.beginTime-minTime)*timeScale,\r
+ r*rowHeight,\r
+ (task.beginTime-minTime)*timeScale,\r
+ (r+1)*rowHeight);\r
+ s.printf(locale,\r
+ "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"green\"/>\n",\r
+ (task.beginTime-minTime)*timeScale,\r
+ r*rowHeight,\r
+ (task.endTime-task.beginTime)*timeScale,\r
+ rowHeight);\r
+ }\r
+ for(Task task : lane.tasks) {\r
+ s.printf(locale,\r
+ "<text x=\"%f\" y=\"%f\">%s</text>\n",\r
+ (task.endTime-minTime)*timeScale,\r
+ (r+0.8)*rowHeight,\r
+ task.name);\r
+ }\r
+ } \r
+ s.println("</svg>");\r
+ }\r
+\r
+ public void visualize2(PrintStream s) {\r
+ long minTime = Long.MAX_VALUE;\r
+ long maxTime = Long.MIN_VALUE;\r
+ ArrayList<Lane> lanes = new ArrayList<Lane>();\r
+ \r
+ for(Task task : tasks) {\r
+ minTime = Math.min(minTime, task.beginTime);\r
+ maxTime = Math.max(maxTime, task.endTime);\r
+ int laneId;\r
+ for(laneId=0;laneId<lanes.size();++laneId)\r
+ if(lanes.get(laneId).nextTime < task.beginTime) \r
+ break;\r
+ Lane lane;\r
+ if(laneId < lanes.size())\r
+ lane = lanes.get(laneId);\r
+ else {\r
+ lane = new Lane();\r
+ lanes.add(lane);\r
+ }\r
+ lane.tasks.add(task);\r
+ lane.nextTime = Math.max(task.endTime, task.beginTime+COLUMN_WIDTH);\r
+ System.out.println(task.name + " -> " + laneId + "[" + task.beginTime + "-" + task.endTime + "]");\r
+ }\r
+ \r
+ double timeScale = 1e-7*5;\r
+ double rowHeight = 30.0;\r
+ Locale locale = Locale.US;\r
+ int row = lanes.size();\r
+ \r
+ s.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");\r
+ s.println("<svg xmlns=\"http://www.w3.org/2000/svg\" overflow=\"visible\" version=\"1.1\">");\r
+ for(long time = minTime ; time < maxTime ; time += 1000000000) {\r
+ s.printf(locale,\r
+ "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"grey\"/>\n",\r
+ (time-minTime)*timeScale,\r
+ 0.0,\r
+ (time-minTime)*timeScale,\r
+ row*rowHeight);\r
+ } \r
+ for(int r = 0;r<lanes.size();++r) {\r
+ Lane lane = lanes.get(r);\r
+ for(Task task : lane.tasks) {\r
+ s.printf(locale,\r
+ "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\"/>\n",\r
+ (task.beginTime-minTime)*timeScale,\r
+ r*rowHeight,\r
+ (task.beginTime-minTime)*timeScale,\r
+ (r+1)*rowHeight);\r
+ s.printf(locale,\r
+ "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"green\"/>\n",\r
+ (task.beginTime-minTime)*timeScale,\r
+ r*rowHeight,\r
+ (task.endTime-task.beginTime)*timeScale,\r
+ rowHeight);\r
+ }\r
+ for(Task task : lane.tasks) {\r
+ s.printf(locale,\r
+ "<text x=\"%f\" y=\"%f\">%s</text>\n",\r
+ (task.endTime-minTime)*timeScale,\r
+ (r+0.8)*rowHeight,\r
+ task.name);\r
+ }\r
+ } \r
+ s.println("</svg>");\r
+ }\r
+ \r
+ public void visualize(PrintStream s) {\r
+ long minTime = Long.MAX_VALUE;\r
+ long maxTime = Long.MIN_VALUE;\r
+ Map<Long, Integer> threads = new HashMap<Long, Integer>(); \r
+ int row = 0;\r
+ \r
+ for(Task task : tasks) {\r
+ minTime = Math.min(minTime, task.beginTime);\r
+ maxTime = Math.max(maxTime, task.endTime);\r
+ if(!threads.containsKey(task.threadId))\r
+ threads.put(task.threadId, row++);\r
+ }\r
+ \r
+ double timeScale = 1e-7*0.8;\r
+ double rowHeight = 60.0;\r
+ Locale locale = Locale.US;\r
+ int textPos[] = new int[row];\r
+ \r
+ s.println("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");\r
+ s.println("<svg xmlns=\"http://www.w3.org/2000/svg\" overflow=\"visible\" version=\"1.1\">");\r
+ for(long time = minTime ; time < maxTime ; time += 1000000000) {\r
+ s.printf(locale,\r
+ "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"grey\"/>\n",\r
+ (time-minTime)*timeScale,\r
+ 0.0,\r
+ (time-minTime)*timeScale,\r
+ row*rowHeight);\r
+ } \r
+ for(Task task : tasks) {\r
+ int r = threads.get(task.threadId);\r
+ s.printf(locale,\r
+ "<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" stroke=\"black\"/>\n",\r
+ (task.beginTime-minTime)*timeScale,\r
+ r*rowHeight,\r
+ (task.beginTime-minTime)*timeScale,\r
+ (r+1)*rowHeight);\r
+ s.printf(locale,\r
+ "<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" fill=\"green\"/>\n",\r
+ (task.beginTime-minTime)*timeScale,\r
+ r*rowHeight,\r
+ (task.endTime-task.beginTime)*timeScale,\r
+ rowHeight);\r
+ }\r
+ for(Task task : tasks) {\r
+ int r = threads.get(task.threadId);\r
+ s.printf(locale,\r
+ "<text x=\"%f\" y=\"%f\">%s</text>\n",\r
+ (task.endTime-minTime)*timeScale,\r
+ (r*3+(textPos[r]++)%2+0.5)*rowHeight/3,\r
+ task.name);\r
+ }\r
+ s.println("</svg>");\r
+ }\r
+ \r
+ public static void main(String[] args) {\r
+ try {\r
+ ThreadLogVisualizer visualizer = new ThreadLogVisualizer();\r
+ visualizer.read(new DataInputStream(new FileInputStream(ThreadLogger.LOG_FILE)));\r
+ visualizer.visualize3(new PrintStream(ThreadLogger.LOG_FILE + ".svg"));\r
+ } catch (FileNotFoundException e) {\r
+ // TODO Auto-generated catch block\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ \r
+}\r