sysperfana/memspyext/com.nokia.s60tools.swmtanalyser/src/com/nokia/s60tools/swmtanalyser/ui/graphs/ThreadsGraph.java
changeset 7 8e12a575a9b5
equal deleted inserted replaced
6:f65f740e69f9 7:8e12a575a9b5
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 package com.nokia.s60tools.swmtanalyser.ui.graphs;
       
    18 
       
    19 import java.util.ArrayList;
       
    20 import java.util.HashMap;
       
    21 import java.util.List;
       
    22 
       
    23 import org.eclipse.draw2d.Graphics;
       
    24 import org.eclipse.draw2d.Polyline;
       
    25 import org.eclipse.draw2d.geometry.PointList;
       
    26 import org.eclipse.swt.SWT;
       
    27 import org.eclipse.swt.graphics.Color;
       
    28 import org.eclipse.swt.graphics.GC;
       
    29 import org.eclipse.swt.graphics.Image;
       
    30 import org.eclipse.swt.graphics.Point;
       
    31 import org.eclipse.swt.graphics.Transform;
       
    32 import org.eclipse.swt.widgets.Display;
       
    33 
       
    34 import com.nokia.s60tools.swmtanalyser.data.CycleData;
       
    35 import com.nokia.s60tools.swmtanalyser.data.ThreadData;
       
    36 import com.nokia.s60tools.swmtanalyser.model.SWMTLogReaderUtils;
       
    37 import com.nokia.s60tools.util.debug.DbgUtility;
       
    38 
       
    39 /**
       
    40  * This class contains all needed logic to paint data related to Threads. 
       
    41  */
       
    42 public class ThreadsGraph extends GenericGraph {
       
    43 
       
    44 	//
       
    45 	// Members
       
    46 	// 
       
    47 	private HashMap<String, ArrayList<ThreadData>> threadData = new HashMap<String, ArrayList<ThreadData>>();	
       
    48 	private HashMap<String, Polyline> samplesData = new HashMap<String, Polyline>();
       
    49 	private double visY;
       
    50 	private double multiplier;
       
    51 	private boolean yAxisNeedsToBeChanged = false;
       
    52 	
       
    53 	/* (non-Javadoc)
       
    54 	 * @see com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph#paint(org.eclipse.draw2d.Graphics)
       
    55 	 */
       
    56 	public void paint(Graphics graphics) {
       
    57 
       
    58 		DbgUtility.println(DbgUtility.PRIORITY_OPERATION, this.getClass().getSimpleName() + "/paint START");
       
    59 
       
    60 		// Getting threads that user has been selected
       
    61 		ArrayList<String> threadsList = this.getUserSelectedItems();
       
    62 		
       
    63 		 if(threadsList == null){
       
    64 			 // No thread data selected for drawing
       
    65 			 return;			 
       
    66 		 }
       
    67 		
       
    68 		// Storing original settings before graphs are painted with case-specific settings
       
    69 		int origLineWidth = graphics.getLineWidth();		
       
    70 		Color origColor = graphics.getForegroundColor();
       
    71 		int origLineStyle = graphics.getLineStyle();
       
    72 		
       
    73 		// Setting graph drawing specific settings
       
    74 		graphics.setLineWidth(CommonGraphConstants.DEFAULT_GRAPH_LINE_WIDTH);		
       
    75 		graphics.setLineStyle(SWT.LINE_SOLID);
       
    76 		
       
    77 		 // Getting cycle time stamps		
       
    78 		 int [] listX = this.calculateTimeIntervals();
       
    79 		 this.lastSampleTime = listX[listX.length-1];
       
    80 		 
       
    81 		// Each thread is drawn by different color stored in external array
       
    82 		 int colorIndex=0;  
       
    83 		 visY  = visualSizeY - CommonGraphConstants.XLEGENDSPACE; 
       
    84 		 
       
    85 		 // Looping through all the threads
       
    86 		 for(String th: threadsList)
       
    87 		 { 
       
    88 			 ArrayList<ThreadData> data = threadData.get(th);
       
    89 				 
       
    90 			 boolean handleDeleted = false;
       
    91 			 
       
    92 			 int[] valuesToBePlotted = new int[data.size()];
       
    93 			 int [] points = new int[valuesToBePlotted.length *2];
       
    94 			
       
    95 			 List<List<Integer>> ListOfSolidLinePoints = new ArrayList<List<Integer>>();
       
    96 			 ArrayList<Integer> solidLinePoints = new ArrayList<Integer>();
       
    97 			 
       
    98 			 for(int i =0, j=0; i<data.size(); i++, j++)
       
    99 			 {
       
   100 				 EventTypes event = this.getEvent();
       
   101 				
       
   102 				 valuesToBePlotted[i] = getEventValueFromThreadData(data.get(i), event);
       
   103 				 DbgUtility.println(DbgUtility.PRIORITY_LOOP, "valuesToBePlotted[i] before scaling: " + valuesToBePlotted[i]);
       
   104 
       
   105 				if (valuesToBePlotted[i] <= 0){
       
   106 					// Not showing zero values to a user, not meaningful data 
       
   107 					DbgUtility.println(DbgUtility.PRIORITY_LOOP, "continued to next Y-value because value was <= 0");
       
   108 					continue;
       
   109 				}
       
   110 				 
       
   111 				 // Scaling both X and Y coordinate according currently used scaling
       
   112 				 int x_point = (int)(listX[i]/getScale());			    	
       
   113 				 int y_point =(int) (visY - valuesToBePlotted[i] /multiplier);
       
   114 
       
   115 				 // Drawing data only if handle has been
       
   116 				 if(!handleDeleted){
       
   117 					 if(y_point > 0){
       
   118 						 solidLinePoints.add(x_point);
       
   119 						 solidLinePoints.add(y_point);	
       
   120 						 DbgUtility.println(DbgUtility.PRIORITY_LOOP, "add 1: x_point: " + x_point + ", y_point: " + y_point);
       
   121 					 }
       
   122 					 else{
       
   123 						    DbgUtility.println(DbgUtility.PRIORITY_LOOP, "skipped because non-positive Y-axis value");
       
   124 					 }
       
   125 				 }
       
   126 				 
       
   127 				 if(data.get(i).isKernelHandleDeleted() && !handleDeleted){
       
   128 					 handleDeleted = true;
       
   129 				 }
       
   130 				 
       
   131 				 if(handleDeleted && data.get(i).getStatus() == CycleData.New)
       
   132 				 {
       
   133 					 handleDeleted = false;
       
   134 					 
       
   135 					 if(y_point > 0){
       
   136 						 // Graphing only positive values
       
   137 						 solidLinePoints.add(x_point);
       
   138 						 solidLinePoints.add(y_point);					 
       
   139 						 DbgUtility.println(DbgUtility.PRIORITY_LOOP, "add 2:x_point: " + x_point + ", y_point: " + y_point);
       
   140 					 }
       
   141 					 else{
       
   142 					    DbgUtility.println(DbgUtility.PRIORITY_LOOP, "skipped because zero value");
       
   143 					 }					 
       
   144 				 }
       
   145 				 
       
   146 				 points[j] = x_point;
       
   147 				 points[++j] = y_point;
       
   148 			 }	
       
   149 			 
       
   150 			 if(solidLinePoints.size() > 0){
       
   151 				 // Adding point for this thread graph, possible to have more instances for same thread name
       
   152 				 ListOfSolidLinePoints.add(solidLinePoints);				 
       
   153 			 }
       
   154 			 
       
   155 			visY  = visualSizeY - CommonGraphConstants.XLEGENDSPACE;
       
   156 							
       
   157 			// Each thread have a separate color
       
   158 			graphics.setForegroundColor(this.getColors().get(colorIndex));
       
   159 						
       
   160 			DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "No of solid lists are " + ListOfSolidLinePoints.size());					
       
   161 				
       
   162 			for(int i=0; i < ListOfSolidLinePoints.size(); i++)
       
   163 			{
       
   164 				int [] solidPts = GraphsUtils.CreateIntArrayFromIntegerList(ListOfSolidLinePoints.get(i));
       
   165 					
       
   166 				if(solidPts != null)
       
   167 				{
       
   168 					if(ListOfSolidLinePoints.size() > 1)
       
   169 					{
       
   170 						int instance_id = i+1;
       
   171 						graphics.drawString("(0" + instance_id + ")", solidPts[0]+2, solidPts[1] - 15);
       
   172 					}
       
   173 					
       
   174 					// Drawing graph based on the stored data points
       
   175 					graphics.drawPolyline(solidPts);
       
   176 					
       
   177 					// Drawing markers to the data points
       
   178 					GraphsUtils.drawMarkers(graphics, solidPts);
       
   179 				}
       
   180 			}
       
   181 				
       
   182 			Polyline line = new Polyline();
       
   183 			line.setPoints(new PointList(points));
       
   184 		
       
   185 			DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "Putting the points list in a map for '" + th + "'.");
       
   186 			samplesData.put(th, line);
       
   187 			 
       
   188 			colorIndex++;
       
   189 		}
       
   190 		 
       
   191 		// Restoring original settings before paint call
       
   192 		graphics.setLineStyle(origLineStyle);
       
   193 		graphics.setForegroundColor(origColor);
       
   194 		graphics.setLineWidth(origLineWidth);
       
   195 
       
   196 		DbgUtility.println(DbgUtility.PRIORITY_OPERATION, this.getClass().getSimpleName() + "/paint END");
       
   197 	}
       
   198 
       
   199 	/* (non-Javadoc)
       
   200 	 * @see com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph#paintYAxis(org.eclipse.swt.graphics.GC)
       
   201 	 */
       
   202 	public void paintYAxis(GC gc)
       
   203 	{	
       
   204 		double visY  = visualSizeY - CommonGraphConstants.XLEGENDSPACE; 
       
   205 		
       
   206 		switch(this.getEvent())
       
   207 		{
       
   208 			case NO_OF_FILES:
       
   209 			case HEAP_ALLOC_CELL_COUNT:
       
   210 			case HEAP_FREE_CELL_COUNT:
       
   211 			case NO_OF_PSHANDLES:
       
   212 				multiplier = GraphsUtils.roundToNearestNumber(maxBytes) / visY;
       
   213 				yAxisNeedsToBeChanged = true;
       
   214 				break;
       
   215 			default:
       
   216 					multiplier = GraphsUtils.prettyMaxBytes(maxBytes) / visY;
       
   217 				break;
       
   218 		}
       
   219 		int countOfYAxisLabels = 10;
       
   220 		double yIncrement = visY / countOfYAxisLabels;
       
   221 		int previousBottom = 0;
       
   222 		
       
   223 		for (int k = countOfYAxisLabels; k >= 0; k--)
       
   224 		{
       
   225 			// location for the value indicator is k * 1/10 the height of the display
       
   226 			int y = (int) (visY - (yIncrement * k));
       
   227 		
       
   228 			int bytes = (int)(yIncrement * multiplier) * k;
       
   229 
       
   230 			String legend = "";
       
   231 			
       
   232 			switch(this.getEvent())
       
   233 			{
       
   234 				case NO_OF_FILES:
       
   235 				case HEAP_ALLOC_CELL_COUNT:
       
   236 				case HEAP_FREE_CELL_COUNT:
       
   237 				case NO_OF_PSHANDLES:
       
   238 					legend += bytes;
       
   239 					break;
       
   240 				default:
       
   241 					//legend += bytes + "B";
       
   242 					if (maxBytes < 10000)
       
   243 					{
       
   244 						legend += bytes + " B"; //$NON-NLS-1$
       
   245 					}
       
   246 					else if (maxBytes <= 500 * 1024)
       
   247 					{
       
   248 						legend += (bytes / 1024) + " KB"; //$NON-NLS-1$
       
   249 					}
       
   250 					else
       
   251 					{
       
   252 						legend +=  MBformat.format(((float) bytes / (1024 * 1024)))  + " MB"; //$NON-NLS-1$
       
   253 					}
       
   254 					break;
       
   255 			}
       
   256 			
       
   257 			Point extent = gc.stringExtent(legend);
       
   258 			
       
   259 			gc.drawLine(CommonGraphConstants.YLEGENDSPACE - 3, (int)y + 1, CommonGraphConstants.YLEGENDSPACE, (int)y + 1);
       
   260 			
       
   261 			if (y >= previousBottom)
       
   262 			{
       
   263 				gc.drawString(legend, CommonGraphConstants.YLEGENDSPACE - extent.x -2, (int)y);
       
   264 				previousBottom = (int)y + extent.y;
       
   265 			}
       
   266 		}
       
   267 		
       
   268 		if(yAxisNeedsToBeChanged)
       
   269 			drawCountLabel(gc, (int)(visY/3));
       
   270 		else
       
   271 			drawBytesLabel(gc, (int)(visY/3));
       
   272 	}
       
   273 
       
   274 	private void fetchEntireDataForSelectedThreads()
       
   275 	{
       
   276 		ArrayList<String> selectedThreads = this.getUserSelectedItems();
       
   277 		SWMTLogReaderUtils utils = new SWMTLogReaderUtils();
       
   278 		
       
   279 		for(String th:selectedThreads)
       
   280 		{
       
   281 			ArrayList<ThreadData> thData = utils.getHeapDataFromAllCycles(th, this.getCyclesData());
       
   282 			threadData.put(th, thData);
       
   283 		}
       
   284 	}
       
   285 	
       
   286 	/* (non-Javadoc)
       
   287 	 * @see com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph#prepareData()
       
   288 	 */
       
   289 	public void prepareData()
       
   290 	{
       
   291 		fetchEntireDataForSelectedThreads();
       
   292 		
       
   293 		 for(String th:getUserSelectedItems())
       
   294 		 {
       
   295 			 ArrayList<ThreadData> data = threadData.get(th);
       
   296 			 
       
   297 			 valuesToBePlotted = new int[data.size()];
       
   298 			 for(int i =0; i<data.size(); i++)
       
   299 			 {
       
   300 				 EventTypes event = this.getEvent();
       
   301 				 valuesToBePlotted[i] = getEventValueFromThreadData(data.get(i), event);
       
   302 				 int maxValue = calculateMaxValue(valuesToBePlotted);
       
   303 				 if(maxValue > maxBytes)
       
   304 					 maxBytes = maxValue;
       
   305 			 }
       
   306 			 
       
   307 		 }
       
   308 		
       
   309 	}
       
   310 	
       
   311 	private int getEventValueFromThreadData(ThreadData thData, EventTypes event)
       
   312 	{
       
   313 		int value = 0;
       
   314 	
       
   315 		if(thData.getStatus() == CycleData.Deleted)
       
   316 			return 0;
       
   317 		
       
   318 		switch(event)
       
   319 		{
       
   320 			case NO_OF_FILES:
       
   321 				value = (int)thData.getOpenFiles();
       
   322 				break;
       
   323 			case MAX_HEAP_SIZE:
       
   324 				value = (int)thData.getMaxHeapSize();
       
   325 				break;
       
   326 			case HEAP_SIZE:
       
   327 				value = (int)thData.getHeapChunkSize();
       
   328 				break;
       
   329 			case HEAP_ALLOC_SPACE:
       
   330 				value = (int)thData.getHeapAllocatedSpace();
       
   331 				break;
       
   332 			case HEAP_FREE_SPACE:
       
   333 				value = (int)thData.getHeapFreeSpace();
       
   334 				break;
       
   335 			case HEAP_ALLOC_CELL_COUNT:
       
   336 				value = (int)thData.getAllocatedCells();
       
   337 				break;
       
   338 			case HEAP_FREE_CELL_COUNT:
       
   339 				value = (int)thData.getFreeCells();
       
   340 				break;
       
   341 			case HEAP_FREE_SLACK:
       
   342 				value = (int)thData.getFreeSlackSize();
       
   343 				break;
       
   344 			case NO_OF_PSHANDLES:
       
   345 				value = (int)thData.getPsHandles();
       
   346 				break;
       
   347 			default:
       
   348 				value = 0;
       
   349 				break;
       
   350 		}
       
   351 		
       
   352 		return value;
       
   353 	}
       
   354 	
       
   355 	/* (non-Javadoc)
       
   356 	 * @see com.nokia.s60tools.swmtanalyser.ui.graphs.GenericGraph#getToolTipText(int, int)
       
   357 	 */
       
   358 	public String getToolTipText(int x, int y)
       
   359 	{
       
   360 		if(y > (int)visY)
       
   361 			return null;
       
   362 		
       
   363 		String text = "";
       
   364 		
       
   365 		double xValue = x + timeOffset;
       
   366 		int scaledX = (int)(xValue * getScale());
       
   367 		
       
   368 		double valY = visY - y;
       
   369 		double scaledY =  valY * multiplier;			
       
   370 		
       
   371 		String yValue = "";
       
   372 				
       
   373 		yValue+= (int)(scaledY);
       
   374 			
       
   375 		switch(this.getEvent())
       
   376 		{
       
   377 			case NO_OF_FILES:
       
   378 			case NO_OF_PSHANDLES:
       
   379 			case HEAP_ALLOC_CELL_COUNT:
       
   380 			case HEAP_FREE_CELL_COUNT:
       
   381 				text += scaledX + " s, " + yValue;
       
   382 				break;
       
   383 			default:
       
   384 				yValue = getFormattedValues(scaledY);
       
   385 				text += scaledX + " s, " + yValue;
       
   386 				break;
       
   387 		}
       
   388 		
       
   389 		for(String th: getUserSelectedItems())
       
   390 		{
       
   391 			Polyline line = samplesData.get(th);
       
   392 			if(line != null && line.containsPoint(x, y))
       
   393 				text += "\n" + th;
       
   394 		
       
   395 		}
       
   396 				
       
   397 		return text; 
       
   398 	}
       
   399 	
       
   400 	/**
       
   401 	 * Get thread data for thread
       
   402 	 * @param thread
       
   403 	 * @return thread data
       
   404 	 */
       
   405 	public ArrayList<ThreadData> getDataForThread(String thread)
       
   406 	{
       
   407 		return this.threadData.get(thread);
       
   408 	}
       
   409 	
       
   410 	/**
       
   411 	 * Draws Bytes label on given gc at given position
       
   412 	 * @param gc
       
   413 	 * @param position
       
   414 	 */
       
   415 	private void drawBytesLabel(GC gc, int position)
       
   416 	{
       
   417 		final Image image = this.getVerticalLabel("Bytes");
       
   418 		gc.setAdvanced(true);
       
   419 		final org.eclipse.swt.graphics.Rectangle rect2 = image.getBounds();
       
   420 		Transform transform = new Transform(Display.getDefault());
       
   421 
       
   422 		transform.translate(rect2.height / 2f, rect2.width / 2f);
       
   423 		transform.rotate(-90);
       
   424 		transform.translate(-rect2.width / 2f, -rect2.height / 2f);
       
   425 
       
   426 		gc.setTransform(transform);
       
   427 		gc.drawImage(image, -position, 0);
       
   428 
       
   429 		transform.dispose();
       
   430 		gc.dispose();				
       
   431 
       
   432 	}
       
   433 	
       
   434 	/**
       
   435 	 * Draws Count label on given gc at given position
       
   436 	 * @param gc
       
   437 	 * @param position
       
   438 	 */
       
   439 	private void drawCountLabel(GC gc, int position)
       
   440 	{
       
   441 		final Image image = this.getVerticalLabel("Count");
       
   442 		gc.setAdvanced(true);
       
   443 		final org.eclipse.swt.graphics.Rectangle rect2 = image.getBounds();
       
   444 		Transform transform = new Transform(Display.getDefault());
       
   445 
       
   446 		transform.translate(rect2.height / 2f, rect2.width / 2f);
       
   447 		transform.rotate(-90);
       
   448 		transform.translate(-rect2.width / 2f, -rect2.height / 2f);
       
   449 
       
   450 		gc.setTransform(transform);
       
   451 		gc.drawImage(image, -position, 0);
       
   452 
       
   453 		transform.dispose();
       
   454 		gc.dispose();				
       
   455 
       
   456 	}
       
   457 	
       
   458 	private String getFormattedValues(double bytes)
       
   459 	{
       
   460 		String scaledY = "";
       
   461 		
       
   462 		if (bytes < 10000)
       
   463 		{
       
   464 			scaledY += Bytes_Format.format(bytes) + " B"; //$NON-NLS-1$
       
   465 		}
       
   466 		else if (bytes <= 500 * 1024)
       
   467 		{
       
   468 			scaledY += Bytes_Format.format(bytes / 1024) + " KB"; //$NON-NLS-1$
       
   469 		}
       
   470 		else
       
   471 		{
       
   472 			scaledY +=  MBformat.format(((float) bytes / (1024 * 1024)))  + " MB"; //$NON-NLS-1$
       
   473 		}
       
   474 		
       
   475 		return scaledY;
       
   476 	}
       
   477 }