sysperfana/perfinvestigator/com.nokia.carbide.cpp.pi.address/src/com/nokia/carbide/cpp/pi/address/GppTraceParser.java
changeset 2 b9ab3b238396
child 5 844b047e260d
equal deleted inserted replaced
1:1050670c6980 2:b9ab3b238396
       
     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 the License "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 
       
    18 package com.nokia.carbide.cpp.pi.address;
       
    19 
       
    20 import java.io.DataInputStream;
       
    21 import java.io.DataOutputStream;
       
    22 import java.io.EOFException;
       
    23 import java.io.File;
       
    24 import java.io.FileInputStream;
       
    25 import java.io.IOException;
       
    26 import java.util.Collection;
       
    27 import java.util.Enumeration;
       
    28 import java.util.Hashtable;
       
    29 import java.util.Iterator;
       
    30 import java.util.StringTokenizer;
       
    31 import java.util.Vector;
       
    32 
       
    33 import com.nokia.carbide.cpp.internal.pi.analyser.NpiInstanceRepository;
       
    34 import com.nokia.carbide.cpp.internal.pi.model.GenericTrace;
       
    35 import com.nokia.carbide.cpp.internal.pi.model.ParsedTraceData;
       
    36 import com.nokia.carbide.cpp.internal.pi.model.Parser;
       
    37 import com.nokia.carbide.cpp.internal.pi.model.TraceDataContainer;
       
    38 
       
    39 
       
    40 public class GppTraceParser extends Parser
       
    41 {
       
    42 //  private String traceVersion;
       
    43   private boolean debug = false;
       
    44   private String profilerVersion;
       
    45   private String samplerVersion;
       
    46   private Hashtable<Integer,GppProcess> processes;
       
    47   private Hashtable<Integer,GppThread> threads;
       
    48   private GppSample[] traceData;
       
    49   private GppThread[] sortedThreads;
       
    50   private TraceDataContainer container; 
       
    51   private Hashtable<Long,String> threadAddressToName;
       
    52 
       
    53   public GppTraceParser() throws IOException
       
    54   {
       
    55     this.processes = new Hashtable<Integer,GppProcess>();
       
    56     this.threads   = new Hashtable<Integer,GppThread>();
       
    57     this.threadAddressToName = new Hashtable<Long,String>();
       
    58   }
       
    59 
       
    60   public ParsedTraceData parse(File traceInput) throws IOException
       
    61   {
       
    62     if (!traceInput.exists())
       
    63     	throw new IOException(Messages.getString("GppTraceParser.0"));  //$NON-NLS-1$
       
    64 
       
    65     DataInputStream dis = new DataInputStream(new FileInputStream(traceInput));
       
    66 	  
       
    67     if (validate(dis) == false)
       
    68     	throw new IOException(Messages.getString("GppTraceParser.1"));  //$NON-NLS-1$
       
    69 
       
    70     long pc = 0;
       
    71     GppThread thread = null;
       
    72     int threadIndexer = 0;
       
    73     int count = 1;
       
    74     int samples = 0;
       
    75     long time = 0;
       
    76 
       
    77     Vector<GppSample> intermediateTraceData = new Vector<GppSample>();
       
    78     
       
    79     // determine the base sampling period (address/thread sampling period) 
       
    80     int addrThreadPeriod = 1;
       
    81     
       
    82     if (traceVersion.indexOf("V2.01") != -1) { //$NON-NLS-1$
       
    83     	addrThreadPeriod =   (dis.readUnsignedByte() << 24)
       
    84 			    		   | (dis.readUnsignedByte() << 16)
       
    85 			    		   | (dis.readUnsignedByte() <<  8)
       
    86 			    		   |  dis.readUnsignedByte();
       
    87     }
       
    88 
       
    89 	// initialize the address/thread base sampling rate
       
    90 	NpiInstanceRepository.getInstance().activeUidSetPersistState(
       
    91 								"com.nokia.carbide.cpp.pi.address.samplingInterval", //$NON-NLS-1$
       
    92 								new Integer(addrThreadPeriod)); //$NON-NLS-1$
       
    93     
       
    94     while (dis.available() > 0)
       
    95     {
       
    96       try
       
    97       {
       
    98         count = 1;
       
    99         int diff = (int)decodeInt(dis);
       
   100  
       
   101         if ((diff & 1) == 1)
       
   102         {
       
   103           diff &= ~1;
       
   104           thread = decodeThread(dis);
       
   105         }
       
   106         else if (diff == 0)
       
   107         {
       
   108           count = (int)decodeUInt(dis);
       
   109         }
       
   110 
       
   111         pc += diff;
       
   112 
       
   113         while (--count >= 0)
       
   114         {
       
   115           samples++;
       
   116           time += addrThreadPeriod;
       
   117           
       
   118           if (samples == 1 && thread == null)
       
   119           {
       
   120 	       	// the first sample may be recorded before its thread's name
       
   121 
       
   122         	// create a new sample object for this sample
       
   123             GppSample gppSample = new GppSample();
       
   124             long pcMod = pc << 32;
       
   125             pcMod = pcMod >>> 32;
       
   126            	gppSample.programCounter = pcMod;
       
   127             gppSample.sampleSynchTime = time;
       
   128               
       
   129             GppThread unknownThread = new GppThread();
       
   130             unknownThread.threadId = -1;
       
   131             unknownThread.threadName = Messages.getString("GppTraceParser.unknown"); //$NON-NLS-1$
       
   132               
       
   133             GppProcess unknownProcess = new GppProcess();
       
   134             unknownProcess.id = -1;
       
   135             unknownProcess.name = Messages.getString("GppTraceParser.unknown"); //$NON-NLS-1$
       
   136             this.processes.put(-1,unknownProcess);
       
   137  
       
   138             unknownThread.process = unknownProcess;
       
   139             unknownThread.index = threadIndexer++;
       
   140               
       
   141             gppSample.thread = unknownThread;
       
   142 
       
   143             this.threads.put(-1,unknownThread);
       
   144 
       
   145             gppSample.thread = unknownThread;
       
   146             intermediateTraceData.add(gppSample);
       
   147           }
       
   148           else if (thread.index >= -1)
       
   149 	      {
       
   150             if (thread.index == -1) thread.index = threadIndexer++;
       
   151 
       
   152             // create a new sample object for this sample
       
   153 
       
   154             GppSample gppSample = new GppSample();
       
   155            	long pcMod = pc << 32;
       
   156            	pcMod = pcMod >>> 32;
       
   157            	
       
   158            	if (thread.threadName.equals("*Native*")) //$NON-NLS-1$
       
   159            		gppSample.programCounter = 0;
       
   160            	else
       
   161            		gppSample.programCounter = pcMod;
       
   162             
       
   163             //System.out.println("PC value:"+pc+" "+Long.toHexString(pc));
       
   164             
       
   165             gppSample.sampleSynchTime = time;
       
   166             gppSample.thread = thread;
       
   167             thread.samples++;
       
   168             intermediateTraceData.add(gppSample);
       
   169           }
       
   170         }
       
   171       }
       
   172       catch (EOFException e) {}
       
   173     }
       
   174     if (debug) System.out.println(Messages.getString("GppTraceParser.2"));  //$NON-NLS-1$
       
   175     // all samples have been parsed
       
   176     this.traceData = new GppSample[intermediateTraceData.size()];
       
   177 
       
   178     // store the trace data into an array
       
   179     intermediateTraceData.toArray(this.traceData);
       
   180 
       
   181     // sort the threads into an ordered array
       
   182     this.sortThreads();
       
   183     
       
   184     container = new TraceDataContainer("GPP_address2threadname",new String[]{"address","threadname"}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       
   185     Enumeration<Long> ke = this.threadAddressToName.keys();
       
   186     Iterator<String>  vi = this.threadAddressToName.values().iterator();
       
   187     
       
   188     while(ke.hasMoreElements())
       
   189     {
       
   190     	Long address = ke.nextElement();
       
   191     	String name = vi.next();
       
   192     	container.addDataToColumn("threadname",name); //$NON-NLS-1$
       
   193     	container.addDataToColumn("address",address); //$NON-NLS-1$
       
   194     }
       
   195     this.threadAddressToName.clear();
       
   196     this.threadAddressToName = null;
       
   197     
       
   198     ParsedTraceData pd = new ParsedTraceData();
       
   199     pd.traceData = this.getTrace();
       
   200         
       
   201     return pd;
       
   202   }
       
   203   
       
   204   private void sortThreads()
       
   205   {
       
   206     if (this.threads != null)
       
   207     {
       
   208       boolean sorted = false;
       
   209 
       
   210       GppThread[] tArray = new GppThread[this.threads.size()];
       
   211       Collection<GppThread> threadCollection = this.threads.values();
       
   212       threadCollection.toArray(tArray);
       
   213 
       
   214       // set initial sort order to the order in which
       
   215       // the threads appear in the array
       
   216       for (int i = 0; i < tArray.length; i++)
       
   217       {
       
   218         tArray[i].sortOrder = i;
       
   219       }
       
   220 
       
   221       // sort threads using bubble sort
       
   222       while (sorted == false)
       
   223       {
       
   224         sorted = true;
       
   225         for (int i = 0; i < tArray.length - 1; i++)
       
   226         {
       
   227           if (tArray[i].samples < tArray[i + 1].samples)
       
   228           {
       
   229               // switch the sort order
       
   230               GppThread store = tArray[i];
       
   231               tArray[i] = tArray[i + 1];
       
   232               tArray[i + 1] = store;
       
   233               sorted = false;
       
   234           }
       
   235         }
       
   236       }
       
   237 
       
   238       // finally, store the ordered array
       
   239       this.sortedThreads = tArray;
       
   240       for (int i=0;i<this.sortedThreads.length;i++)
       
   241       {
       
   242         this.sortedThreads[i].sortOrder = i;
       
   243       }
       
   244 
       
   245     }
       
   246   }
       
   247 
       
   248   private boolean validate(DataInputStream dis) throws IOException
       
   249   {
       
   250     String data = decodeName(dis);
       
   251     if (debug) System.out.println(Messages.getString("GppTraceParser.3")+data);  //$NON-NLS-1$
       
   252     if (data.equals("profile")) //pre 1.10 //$NON-NLS-1$
       
   253     if (decodeUInt(dis) == 1) return true;
       
   254         
       
   255     if (data.startsWith("Bappea_GPP_V")) //version 1.20 //$NON-NLS-1$
       
   256     {
       
   257         try
       
   258         {
       
   259         	int separatorIndex = data.indexOf("#"); //$NON-NLS-1$
       
   260 	        this.traceVersion = data.substring(data.indexOf("_")+1,separatorIndex); //$NON-NLS-1$
       
   261 	    }
       
   262 	    catch (Exception e)
       
   263 	    {
       
   264 	    	return false;
       
   265 	    }
       
   266     
       
   267     	StringTokenizer st = new StringTokenizer(data,"#"); //$NON-NLS-1$
       
   268       	while(st.hasMoreElements())
       
   269     	{
       
   270     		String id = st.nextToken();
       
   271     		if (id.equals("Prof")) //$NON-NLS-1$
       
   272     		{
       
   273     			this.profilerVersion = st.nextToken();
       
   274     		}
       
   275     		else if (id.equals("Samp"))  //$NON-NLS-1$
       
   276     		{
       
   277     			this.samplerVersion = st.nextToken();
       
   278     		}
       
   279     	}
       
   280                
       
   281         System.out.println(Messages.getString("GppTraceParser.4")+traceVersion+Messages.getString("GppTraceParser.5")+profilerVersion+Messages.getString("GppTraceParser.6")+samplerVersion);    //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       
   282 		
       
   283 		if (   (traceVersion.indexOf("V1.10") != -1)	//$NON-NLS-1$
       
   284 			|| (traceVersion.indexOf("V1.64") != -1)	//$NON-NLS-1$
       
   285 			|| (traceVersion.indexOf("V2.01") != -1))	//$NON-NLS-1$
       
   286             return true;
       
   287       	else
       
   288       		return false;
       
   289     }
       
   290     
       
   291     return false;
       
   292   }
       
   293 
       
   294   	public static void encodeInt(int number, DataOutputStream dos) throws IOException
       
   295 	{
       
   296 		int digit;
       
   297 		for (;;) {
       
   298 			digit = number & 0x7f;
       
   299 			if ((number >> 6) == (number >> 7))
       
   300 				break;
       
   301 			number >>= 7;
       
   302 			dos.write(digit);
       
   303 		}
       
   304 		dos.write(digit | 0x80);
       
   305 		
       
   306 		dos.flush();
       
   307 	}
       
   308 	
       
   309 	public static void encodeUInt(int number, DataOutputStream dos) throws IOException
       
   310 	{
       
   311 		int digit;
       
   312 		for (;;) {
       
   313 			digit = number & 0x7f;
       
   314 			number >>= 7;
       
   315 			if (number <= 0)
       
   316 				break;
       
   317 			dos.write(digit);
       
   318 		}
       
   319 		dos.write(digit | 0x80);		
       
   320 	}
       
   321   
       
   322   public static long decodeInt(DataInputStream dis) throws IOException
       
   323   {
       
   324     //System.out.println("DECODING INT");
       
   325 
       
   326 	int val = 0;
       
   327     int shift = 0;
       
   328     int data;
       
   329     do
       
   330     {
       
   331       data = dis.readUnsignedByte();
       
   332       //System.out.print(":"+Integer.toHexString(data));
       
   333       if (data < 0)
       
   334     	  throw new IOException(Messages.getString("GppTraceParser.7"));  //$NON-NLS-1$
       
   335       val |= (data & 0x7f) << shift;
       
   336       shift += 7;
       
   337     } while ((data & 0x80) == 0);
       
   338 
       
   339     if (shift < 32)
       
   340     {
       
   341       shift = 32 - shift;
       
   342       val = val << shift >> shift;
       
   343     }
       
   344     //System.out.println("read int"+(val & 0xffffffff));
       
   345 
       
   346     return (val);
       
   347   }
       
   348 
       
   349 
       
   350   public static long decodeUInt(DataInputStream dis) throws IOException
       
   351   {
       
   352     //System.out.println("DECODING UINT");
       
   353     long val = 0;
       
   354     int shift = 0;
       
   355     int data;
       
   356     do
       
   357     {
       
   358       data = dis.readUnsignedByte();
       
   359       //System.out.println("read byte:"+Integer.toHexString(data));
       
   360       if (data < 0)
       
   361     	  throw new IOException(Messages.getString("GppTraceParser.8"));  //$NON-NLS-1$
       
   362       val |= (data & 0x7f) << shift;
       
   363       shift += 7;
       
   364     } while ((data & 0x80) == 0);
       
   365 
       
   366     //System.out.println("read unsigned int"+val);
       
   367     return val;
       
   368   }
       
   369 
       
   370 
       
   371   private String decodeName(DataInputStream dis) throws IOException
       
   372   {
       
   373     //System.out.println("DECODING NAME");
       
   374 
       
   375     int length = dis.readUnsignedByte();
       
   376     //System.out.println("name length "+Integer.toHexString(length));
       
   377     byte[] data = new byte[length];
       
   378     dis.read(data);
       
   379     //System.out.println("Read name:"+new String(data));
       
   380     return new String(data);
       
   381   }
       
   382 
       
   383   private GppProcess decodeProcess(DataInputStream dis) throws IOException
       
   384   {
       
   385     //System.out.println("DECODING PROCESS");
       
   386     Integer pid = new Integer((int)decodeUInt(dis));
       
   387 
       
   388     if (this.processes.containsKey(pid))
       
   389     {
       
   390       return (GppProcess)this.processes.get(pid);
       
   391     }
       
   392     else
       
   393     {
       
   394       GppProcess np = new GppProcess();
       
   395       np.id = pid;
       
   396       np.name = decodeName(dis);
       
   397       this.processes.put(pid,np);
       
   398       return np;
       
   399     }
       
   400   }
       
   401 
       
   402   private GppThread decodeThread(DataInputStream dis) throws IOException
       
   403   {
       
   404     //System.out.println("DECODING THREAD");
       
   405     Integer tid = new Integer((int)decodeUInt(dis));
       
   406 
       
   407     if (this.threads.containsKey(tid))
       
   408     {
       
   409       return (GppThread)this.threads.get(tid);
       
   410     }
       
   411 
       
   412     GppProcess p = decodeProcess(dis);
       
   413     String name = decodeName(dis);
       
   414     
       
   415     try
       
   416 	{
       
   417     	if (name.endsWith("]")) //$NON-NLS-1$
       
   418     	{
       
   419     		String l = name.substring(name.lastIndexOf("[")+1,name.lastIndexOf("]")); //$NON-NLS-1$ //$NON-NLS-2$
       
   420     		Long threadAddress = Long.decode("0x"+l); //$NON-NLS-1$
       
   421     		this.threadAddressToName.put(threadAddress,name);
       
   422     		name = name.substring(0,name.lastIndexOf("[")); //$NON-NLS-1$
       
   423     	}
       
   424 	}
       
   425     catch (Exception e)
       
   426 	{
       
   427     	e.printStackTrace();
       
   428 	}
       
   429 
       
   430     GppThread nt = new GppThread();
       
   431     nt.threadId = tid;
       
   432     nt.threadName = name;
       
   433     nt.process = p;
       
   434     nt.index = -1;
       
   435 
       
   436     this.threads.put(tid,nt);
       
   437 
       
   438     return nt;
       
   439   }
       
   440   
       
   441   private GenericTrace getTrace()
       
   442   {
       
   443   	GppTrace trace = new GppTrace();
       
   444   	for (int i = 0; i < traceData.length; i++)
       
   445   	{
       
   446   		trace.addSample(this.traceData[i]);
       
   447   	}
       
   448   	return trace;
       
   449   }
       
   450 }
       
   451