blob: 465ff622f12f4f61a89006d8b598ee610f5f9a4f [file] [log] [blame]
/*******************************************************************************
* (C) Copyright 2010, 2018 IBM Corp. and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Thavidu Ranatunga (IBM) - Initial implementation.
*******************************************************************************/
package org.eclipse.linuxtools.internal.perf;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.linuxtools.internal.perf.model.PMCommand;
import org.eclipse.linuxtools.internal.perf.model.PMDso;
import org.eclipse.linuxtools.internal.perf.model.PMEvent;
import org.eclipse.linuxtools.internal.perf.model.PMFile;
import org.eclipse.linuxtools.internal.perf.model.PMSymbol;
import org.eclipse.linuxtools.internal.perf.model.TreeParent;
import org.eclipse.linuxtools.internal.perf.ui.PerfProfileView;
import org.eclipse.linuxtools.profiling.launch.ConfigUtils;
import org.eclipse.linuxtools.tools.launch.core.factory.RuntimeProcessFactory;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
public class PerfCore {
private static String spitStream(BufferedReader br, String blockTitle, PrintStream print) {
StringBuffer strBuf = new StringBuffer();
String line = null;
try {
while (( line = br.readLine()) != null){
strBuf.append(line);
strBuf.append("\n"); //$NON-NLS-1$
}
} catch (IOException e) {
logException(e);
}
String str = strBuf.toString();
if (!str.trim().isEmpty() && print != null) {
print.println(blockTitle + ": \n" +str + "\n END OF " + blockTitle); //$NON-NLS-1$ //$NON-NLS-2$
}
return str;
}
// Maps event lists to host names for caching
private static Map<String,Map<String, List<String>>> eventsHostMap = null;
private static Map<String,List<String>> eventList = null;
/**
* Gets the list of events for a given launch configuration. Uses a cache for each host
* @param config
* @return
*/
public static Map<String,List<String>> getEventList(ILaunchConfiguration config) {
String projectHost = getHostName(config);
if(eventsHostMap == null){
eventsHostMap = new HashMap<>();
}
// local projects have null hosts
if(projectHost == null){
projectHost = "local"; //$NON-NLS-1$
}
eventList = eventsHostMap.get(projectHost);
if(eventList == null){
eventList = loadEventList(config);
eventsHostMap.put(projectHost, eventList);
}
return eventList;
}
/**
*
* @param config
* @return the name of the host in which the config's project is stored
*/
private static String getHostName(ILaunchConfiguration config){
String projectName = null;
try {
projectName = config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); //$NON-NLS-1$
} catch (CoreException e) {
return null;
}
if (projectName.isEmpty()) {
return null;
}
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
if(project == null){
return null;
}
URI projectURI = project.getLocationURI();
if (projectURI == null) {
Status status = new Status(IStatus.WARNING, PerfPlugin.PLUGIN_ID,
NLS.bind(Messages.MsgNoProjectError, projectName));
PerfPlugin.getDefault().getLog().log(status);
return null;
}
return project.getLocationURI().getHost();
}
public static IProject getProject(ILaunchConfiguration config){
if(config == null){
return null;
} else {
try {
String projectName = ConfigUtils.getProjectName(config);
// an empty string is not a legal path to file argument for ConfigUtils.getProject
if (projectName != null && !projectName.isEmpty()) {
return ConfigUtils.getProject(projectName);
}
} catch (CoreException e1) {
logException(e1);
}
}
return null;
}
private static Map<String,List<String>> loadEventList(ILaunchConfiguration config){
Map<String,List<String>> events = new HashMap<>();
IProject project = getProject(config);
if (!PerfCore.checkPerfInPath(project)) {
return events;
}
Process p = null;
BufferedReader input = null;
try {
// Execute "perf list" to get list of all symbolic event types.
// Alternatively can try with -i flag.
p = RuntimeProcessFactory.getFactory().exec(new String[] {PerfPlugin.PERF_COMMAND, "list"}, project); //(char 1 as -t is a custom field seperator //$NON-NLS-1$
/*
* Old versions of Perf will send events list to stderr instead of stdout
* Checking if stdout is empty then read from stderr
*/
input = new BufferedReader(new InputStreamReader(p.getInputStream()));
} catch( IOException e ) {
logException(e);
}
return parseEventList(input);
}
public static Map<String,List<String>> parseEventList (BufferedReader input){
Map<String,List<String>> events = new HashMap<>();
String line;
try {
// Process list of events. Each line is of the form <event>\s+<category>.
while (( line = input.readLine()) != null){
if (line.contains("[")) { //$NON-NLS-1$
String event;
String category;
if (line.contains(PerfPlugin.STRINGS_HWBREAKPOINTS)) {
category = PerfPlugin.STRINGS_HWBREAKPOINTS;
event = line.substring(1,line.indexOf('[', 0)).trim();
} else if (line.contains(PerfPlugin.STRINGS_RAWHWEvents)) {
category = PerfPlugin.STRINGS_RAWHWEvents;
event = line.substring(1,line.indexOf('[', 0)).trim();
} else {
event = line.substring(1,line.indexOf('[', 0)).trim();
if (event.contains("OR")) { //$NON-NLS-1$
event = event.split("OR")[0]; //filter out the abbreviations. //$NON-NLS-1$
}
category = line.replaceFirst(".*\\[(.+)\\]", "$1").trim(); //$NON-NLS-1$ //$NON-NLS-2$
}
List<String> categoryEvents = events.get(category);
if (categoryEvents == null) {
categoryEvents = new ArrayList<>();
events.put(category, categoryEvents);
}
categoryEvents.add(event.trim());
}
}
} catch (IOException e) {
logException(e);
} finally {
if (null != input) {
try {
input.close();
} catch (IOException e) {
}
}
}
return events;
}
//Gets the current version of perf
public static PerfVersion getPerfVersion(ILaunchConfiguration config) {
IProject project = getProject(config);
Process p = null;
try {
p = RuntimeProcessFactory.getFactory().exec(new String [] {PerfPlugin.PERF_COMMAND, "--version"}, project); //$NON-NLS-1$
} catch (IOException e) {
// Issue warning to avoid AERI reports whenever user is missing perf
Status status = new Status(IStatus.WARNING, PerfPlugin.PLUGIN_ID,
e.getMessage());
PerfPlugin.getDefault().getLog().log(status);
}
if (p == null) {
return null;
}
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String perfVersion = spitStream(input, "Perf --version", null); //$NON-NLS-1$
int index = perfVersion.indexOf('-');
if (index > 0) {
perfVersion = perfVersion.substring(0, index);
}
Pattern pattern = Pattern.compile("\\D*((\\d|\\.)+)"); //$NON-NLS-1$
Matcher matcher = pattern.matcher(perfVersion);
if (matcher.matches()) {
return new PerfVersion(matcher.group(1));
}
return null;
}
public static boolean checkPerfInPath(IProject project) {
try {
Process p = RuntimeProcessFactory.getFactory().exec(new String [] {PerfPlugin.PERF_COMMAND, "--version"}, project); //$NON-NLS-1$
return (p != null);
} catch (IOException e) {
return false;
}
}
//Generates a perf record command string with the options set in the given config. (If null uses default).
public static String [] getRecordString(ILaunchConfiguration config) {
String [] base = new String [] {PerfPlugin.PERF_COMMAND, "record"}; //$NON-NLS-1$
if (config == null) {
return base;
} else {
ArrayList<String> newCommand = new ArrayList<>();
newCommand.addAll(Arrays.asList(base));
try {
if (config.getAttribute(PerfPlugin.ATTR_Record_Realtime, PerfPlugin.ATTR_Record_Realtime_default)) {
newCommand.add("-r"); //$NON-NLS-1$
int priority = config.getAttribute(PerfPlugin.ATTR_Record_Realtime_Priority, PerfPlugin.ATTR_Record_Realtime_Priority_default);
newCommand.add(Integer.toString(priority));
}
if (config.getAttribute(PerfPlugin.ATTR_Record_Verbose, PerfPlugin.ATTR_Record_Verbose_default))
newCommand.add("-v"); //$NON-NLS-1$
if (config.getAttribute(PerfPlugin.ATTR_Multiplex, PerfPlugin.ATTR_Multiplex_default))
newCommand.add("-M"); //$NON-NLS-1$
List<?> selE = config.getAttribute(PerfPlugin.ATTR_SelectedEvents, PerfPlugin.ATTR_SelectedEvents_default);
if (!config.getAttribute(PerfPlugin.ATTR_DefaultEvent, PerfPlugin.ATTR_DefaultEvent_default)
&& selE != null) {
for(Object e : selE) {
newCommand.add("-e"); //$NON-NLS-1$
newCommand.add((String)e);
}
}
} catch (CoreException e) { }
return newCommand.toArray(new String[] {});
}
}
public static String[] getReportString(ILaunchConfiguration config, String perfDataLoc) {
ArrayList<String> base = new ArrayList<>();
base.addAll(Arrays.asList(new String [] {PerfPlugin.PERF_COMMAND, "report", "--sort", "comm,dso,sym", "-n", "-t", "" + (char)1 }));//(char 1 as -t is a custom field seperator) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
if (config != null) {
try {
String kernelLoc = config.getAttribute(PerfPlugin.ATTR_Kernel_Location, PerfPlugin.ATTR_Kernel_Location_default);
if (!kernelLoc.equals(PerfPlugin.ATTR_Kernel_Location_default)) {
base.add("--vmlinux"); //$NON-NLS-1$
base.add(kernelLoc);
}
if (config.getAttribute(PerfPlugin.ATTR_ModuleSymbols, PerfPlugin.ATTR_ModuleSymbols_default)) {
base.add("-m"); //$NON-NLS-1$
}
/*
* danielhb, 12/14/2011 - some systems, like ubuntu and sles, does not have
* the -U option. The binary fails to execute in those systems when this
* option is enabled.
* I'm disabling it to make the plug-in runnable for them. This
* will probably need to be revisited in the future, probably when this
* flag is implemented by the Perf binary of those systems.
*/
/*
if (config.getAttribute(PerfPlugin.ATTR_HideUnresolvedSymbols, PerfPlugin.ATTR_HideUnresolvedSymbols_default))
base.add("-U");
*/
if (perfDataLoc != null) {
base.add("-i"); //$NON-NLS-1$
base.add(perfDataLoc);
}
} catch (CoreException e) { }
}
return base.toArray( new String[base.size()] );
}
public static String[] getAnnotateString(ILaunchConfiguration config, String dso, String symbol, String perfDataLoc, boolean oldPerfVersion) {
ArrayList<String> base = new ArrayList<>();
if (oldPerfVersion) {
base.addAll( Arrays.asList( new String[]{PerfPlugin.PERF_COMMAND, "annotate", "-s", symbol, "-l", "-P"} ) ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
} else {
base.addAll( Arrays.asList( new String[]{PerfPlugin.PERF_COMMAND, "annotate", "--stdio", "-d", dso, "-s", symbol, "-l", "-P"} ) ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$
}
if (config != null) {
try {
String kernelLoc = config.getAttribute(PerfPlugin.ATTR_Kernel_Location, PerfPlugin.ATTR_Kernel_Location_default);
if (!kernelLoc.equals(PerfPlugin.ATTR_Kernel_Location_default)) {
base.add("--vmlinux"); //$NON-NLS-1$
base.add(kernelLoc);
}
if (config.getAttribute(PerfPlugin.ATTR_ModuleSymbols, PerfPlugin.ATTR_ModuleSymbols_default)) {
base.add("-m"); //$NON-NLS-1$
}
if (perfDataLoc != null) {
base.add("-i"); //$NON-NLS-1$
base.add(perfDataLoc);
}
} catch (CoreException e) { }
}
/*
* Some versions of perf annotate hangs while waiting for an input.
* Redirect input from an empty file (or /dev/null) to avoid that behavior.
*/
base.add("<"); //$NON-NLS-1$
base.add("/dev/null"); //$NON-NLS-1$
//(Annotate string per symbol)
return base.toArray( new String[base.size()] );
}
// Runs assuming perf.data has already been recorded, environ and workingDir can be set to null to use default
//perfDataLoc is optional - it is used to provide a pre-existing data file instead of something recorded from
//whatever project is being profiled. It is only used for junit tests atm.
public static void report(ILaunchConfiguration config, IPath workingDir, IProgressMonitor monitor, String perfDataLoc, PrintStream print) {
IProject project = getProject(config);
TreeParent invisibleRoot = PerfPlugin.getDefault().clearModelRoot();
PerfVersion perfVersion = getPerfVersion(config);
boolean oldPerfVersion = false;
if (perfVersion == null) {
if (print != null) {
print.println("ERROR: Unable to find Perf version, please verify it is installed and on the run path"); //$NON-NLS-1$
return;
}
} else if (!perfVersion.isNewer(new PerfVersion(0, 0, 2))) {
oldPerfVersion = true;
if (print != null) { print.println("WARNING: You are running an older version of Perf, please update if you can. The plugin may produce unpredictable results."); } //$NON-NLS-1$
}
BufferedReader input = null;
BufferedReader error = null;
Process p = null;
if (monitor != null && monitor.isCanceled()) {
return;
}
try {
if (workingDir==null) {
p = RuntimeProcessFactory.getFactory().exec(getReportString(config, perfDataLoc), project);
PerfPlugin.getDefault().setPerfProfileData(new Path(perfDataLoc));
PerfPlugin.getDefault().setWorkingDir(project.getLocation());
} else {
String defaultPerfDataLoc = workingDir.toOSString() + PerfPlugin.PERF_DEFAULT_DATA;
p = RuntimeProcessFactory.getFactory().exec(getReportString(config, defaultPerfDataLoc), project);
PerfPlugin.getDefault().setPerfProfileData(new Path(defaultPerfDataLoc));
PerfPlugin.getDefault().setWorkingDir(workingDir);
}
input = new BufferedReader(new InputStreamReader(p.getInputStream()));
error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
//spitting error stream moved to end of while loop, due to commenting of p.waitFor()
} catch( IOException e ) {
logException(e);
}
PerfCore.parseRemoteReport(config, workingDir, monitor, perfDataLoc, print,
invisibleRoot, oldPerfVersion, input, error, project);
}
/**
* Parse and build a tree model from the report of a perf data file
* @param config launch configuration
* @param workingDir working directory configuration
* @param monitor monitor
* @param perfDataLoc location of perf data file
* @param print print stream
* @param invisibleRoot root of the model
* @param oldPerfVersion boolean old perf version flag
* @param input input stream from perf data file report
* @param error output stream to where all standard error is written to
*/
public static void parseReport(ILaunchConfiguration config,
IPath workingDir, IProgressMonitor monitor, String perfDataLoc,
PrintStream print, TreeParent invisibleRoot,
boolean oldPerfVersion, BufferedReader input, BufferedReader error) {
PerfCore.parseRemoteReport(config, workingDir, monitor, perfDataLoc, print,
invisibleRoot, oldPerfVersion, input, error, null);
}
private static void parseRemoteReport(ILaunchConfiguration config,
IPath workingDir, IProgressMonitor monitor, String perfDataLoc,
PrintStream print, TreeParent invisibleRoot,
boolean oldPerfVersion, BufferedReader input, BufferedReader error, IProject project) {
if (monitor != null && monitor.isCanceled()) {
return;
}
String line = null;
String items[];
float percent;
Process p = null;
double samples;
String comm,dso,symbol;
boolean kernelFlag;
PMEvent currentEvent = null;
PMCommand currentCommand = null;
PMDso currentDso = null;
PMFile currentFile = null;
PMSymbol currentSym = null;
try {
while (( line = input.readLine()) != null){
if (monitor != null && monitor.isCanceled()) {
return;
}
// line containing report information
if ((line.startsWith("#"))) { //$NON-NLS-1$
if (line.contains("Events:") || line.contains("Samples:")) { //$NON-NLS-1$ //$NON-NLS-2$
// ignore lost samples as the plugin has no logic for handling them
if (line.startsWith("# Total Lost Samples:")) { //$NON-NLS-1$
continue;
}
String[] tmp = line.trim().split(" "); //$NON-NLS-1$
String event = tmp[tmp.length - 1];
// In this case, the event name is single quoted
if (line.contains("Samples:")){ //$NON-NLS-1$
event = event.substring(1, event.length() -1);
}
currentEvent = new PMEvent(event);
invisibleRoot.addChild(currentEvent);
currentCommand = null;
currentDso = null;
} else if (line.contains("Samples:")) { //"samples" was used instead of events in an older version, some incompatibilities may arise. //$NON-NLS-1$
if (print != null) { print.println("WARNING: You are running an older version of Perf, please update if you can. The plugin may produce unpredictable results."); } //$NON-NLS-1$
invisibleRoot.addChild(new PMEvent("WARNING: You are running an older version of Perf, the plugin may produce unpredictable results.")); //$NON-NLS-1$
}
// contains profiled information
} else {
items = line.trim().split(""+(char)1); // using custom field separator. for default whitespace use " +" //$NON-NLS-1$
if (items.length != 5) {
continue;
}
percent = Float.parseFloat(items[0].replace("%", "")); //$NON-NLS-1$ //$NON-NLS-2$
samples = Double.parseDouble(items[1].trim()); //samples column
comm = items[2].trim(); //command column
dso = items[3].trim(); //dso column
symbol = items[4].trim(); //symbol column
kernelFlag = (""+symbol.charAt(1)).equals("k"); //$NON-NLS-1$ //$NON-NLS-2$
// initialize current command if it doesn't exist
if ((currentCommand == null) || (!currentCommand.getName().equals(comm))) {
currentCommand = (PMCommand) currentEvent.getChild(comm);
if(currentCommand == null) {
currentCommand = new PMCommand(comm);
currentEvent.addChild(currentCommand);
}
}
// initialize current dso if it doesn't exist
if ((currentDso == null) || (!currentDso.getName().equals(dso))) {
currentDso = (PMDso) currentCommand.getChild(dso);
if (currentDso == null) {
currentDso = new PMDso(dso,kernelFlag);
currentCommand.addChild(currentDso);
}
}
/*
* Initialize the current file, and symbol
*
* We won't know the name of the file containing the symbol
* until we run 'perf annotate' to resolve it, so for now we
* attach all symbols as children of 'Unfiled Symbols'.
*/
currentFile = currentDso.getFile(PerfPlugin.STRINGS_UnfiledSymbols);
currentSym = new PMSymbol(symbol, percent, samples);
currentFile.addChild(currentSym);
}
}
} catch (IOException e) {
logException(e);
}
spitStream(error,"Perf Report", print); //$NON-NLS-1$
boolean SourceLineNumbers = PerfPlugin.ATTR_SourceLineNumbers_default;
boolean Kernel_SourceLineNumbers = PerfPlugin.ATTR_Kernel_SourceLineNumbers_default;
try {
// Check if resolving source file/line numbers is selected
SourceLineNumbers = config.getAttribute(PerfPlugin.ATTR_SourceLineNumbers, PerfPlugin.ATTR_SourceLineNumbers_default);
Kernel_SourceLineNumbers = config.getAttribute(PerfPlugin.ATTR_Kernel_SourceLineNumbers, PerfPlugin.ATTR_Kernel_SourceLineNumbers_default);
} catch (CoreException e2) {
SourceLineNumbers = false;
}
if (monitor != null && monitor.isCanceled()) {
return;
}
boolean hasProfileData = invisibleRoot.getChildren().length != 0;
if (SourceLineNumbers) {
for (TreeParent ev : invisibleRoot.getChildren()) {
if (!(ev instanceof PMEvent)) continue;
for (TreeParent cmd : ev.getChildren()) {
if (!(cmd instanceof PMCommand)) continue;
for (TreeParent d : cmd.getChildren()) {
if (!(d instanceof PMDso)) continue;
currentDso = (PMDso)d;
if ((!Kernel_SourceLineNumbers) && currentDso.isKernelDso()) continue;
for (TreeParent s : currentDso.getFile(PerfPlugin.STRINGS_UnfiledSymbols).getChildren()) {
if (!(s instanceof PMSymbol)) continue;
if (monitor != null && monitor.isCanceled()) {
return;
}
currentSym = (PMSymbol)s;
String[] annotateCmd;
if (workingDir == null) {
annotateCmd = getAnnotateString(config, currentDso.getName(), currentSym.getName().substring(4), perfDataLoc, oldPerfVersion);
} else {
String perfDefaultDataLoc = workingDir + "/" + PerfPlugin.PERF_DEFAULT_DATA; //$NON-NLS-1$
annotateCmd = getAnnotateString(config, currentDso.getName(), currentSym.getName().substring(4), perfDefaultDataLoc, oldPerfVersion);
}
try {
if(project==null) {
p = Runtime.getRuntime().exec(annotateCmd);
} else {
StringBuffer sb = new StringBuffer();
ArrayList<String> al = new ArrayList<>();
/*
* Wrap the whole Perf annotate line as a single argument of sh command
* so that any IO redirection will take effect. Change to working directory before run perf annotate.
* It results on a command string as 'sh', '-c', 'cd <workindir> && perf annotate <args> < /dev/null'
*/
al.add("sh"); //$NON-NLS-1$
al.add("-c"); //$NON-NLS-1$
if(workingDir != null) {
sb.append("cd " + workingDir.toOSString() + " && "); //$NON-NLS-1$ //$NON-NLS-2$
}
for(int i=0; i<annotateCmd.length; i++) {
sb.append(annotateCmd[i]);
sb.append(" "); //$NON-NLS-1$
}
al.add(sb.toString());
p = RuntimeProcessFactory.getFactory().exec(al.toArray(new String[]{}), project);
}
input = new BufferedReader(new InputStreamReader(p.getInputStream()));
error = new BufferedReader(new InputStreamReader(p.getErrorStream()));
} catch (IOException e) {
logException(e);
}
PerfCore.parseAnnotation(monitor, input, workingDir, currentDso, currentSym);
}
if (currentDso.getFile(PerfPlugin.STRINGS_UnfiledSymbols).getChildren().length == 0) {
currentDso.removeChild(currentDso.getFile(PerfPlugin.STRINGS_UnfiledSymbols));
}
spitStream(error,"Perf Annotate", print); //$NON-NLS-1$
}
}
}
}
if (print != null) {
if (hasProfileData) {
print.println("Profile data loaded into Perf Profile View."); //$NON-NLS-1$
} else {
print.println("No profile data generated to be displayed."); //$NON-NLS-1$
}
}
}
/**
* Parse annotation file for a dso given a symbol
* @param monitor monitor
* @param input annotation file input stream
* @param workingDir working directory configuration
* @param currentDso dso
* @param currentSym symbol
*/
public static void parseAnnotation(IProgressMonitor monitor,
BufferedReader input, IPath workingDir, PMDso currentDso,
PMSymbol currentSym) {
if (monitor != null && monitor.isCanceled()) {
return;
}
boolean grabBlock = false;
boolean blockStarted = false;
String dsoName,lineRef;
String line = null;
String items[];
float percent;
try {
while (( line = input.readLine()) != null){
if (line.startsWith("Sorted summary for file")) { //$NON-NLS-1$
grabBlock = true;
dsoName = line.replace("Sorted summary for file ",""); //$NON-NLS-1$ //$NON-NLS-2$
blockStarted = false;
if ((workingDir != null) && (dsoName.startsWith("./"))) { //$NON-NLS-1$
if (workingDir.toOSString().endsWith("/")) { //$NON-NLS-1$
dsoName = workingDir.toOSString() + dsoName.substring(2); // path already ends with '/', so trim './'
} else {
dsoName = workingDir.toOSString() + dsoName.substring(1); // path doesn't have '/', so trim just the '.'
}
}
currentDso.setPath(dsoName);
} else if (line.startsWith("---")) { //$NON-NLS-1$
if (blockStarted) {
blockStarted = false;
grabBlock = false;
} else {
blockStarted = true;
}
} else if (grabBlock && blockStarted) {
//process the line.
items = line.trim().split(" +"); //$NON-NLS-1$
if (items.length != 2) {
continue;
}
percent = Float.parseFloat(items[0]);
lineRef = items[1];
items = lineRef.split(":"); //$NON-NLS-1$
if (currentDso == null) {
//if (PerfPlugin.DEBUG_ON) System.err.println("Parsed line ref without being in valid block, shouldn't happen.");
break;
} else {
int lineNum = -1;
try {
/*
* May not have line number when parsing a line like "100.00 [vdso][7ffce9fdbda0]"
*/
if( items.length > 1) {
lineNum = Integer.parseInt(items[1]);
}
} catch (NumberFormatException e) {
// leave line number as -1
}
currentSym.addPercent(lineNum, percent);
// Symbol currently in 'Unfiled Symbols' but we now know the actual parent
if (currentSym.getParent().getName().equals(PerfPlugin.STRINGS_UnfiledSymbols)) {
currentSym.getParent().removeChild(currentSym);
currentDso.getFile(items[0]).addChild(currentSym);
// Symbol has 2 (or more) parents
} else if (!((PMFile)currentSym.getParent()).getPath().equals(items[0])) {
currentSym.markConflict();
currentSym.getParent().removeChild(currentSym);
currentDso.getFile(PerfPlugin.STRINGS_MultipleFilesForSymbol).addChild(currentSym);
}
}
}
}
} catch (IOException e) {
logException(e);
}
}
public static void refreshView (final String title) {
Display.getDefault().syncExec(() -> {
try {
PerfProfileView view = (PerfProfileView) PlatformUI
.getWorkbench().getActiveWorkbenchWindow()
.getActivePage().showView(PerfPlugin.VIEW_ID);
view.setContentDescription(title);
view.refreshModel();
} catch (PartInitException e) {
logException(e);
}
});
}
/**
* Log specified exception.
* @param e Exception to log.
*/
public static void logException(Exception e) {
Status status = new Status(IStatus.ERROR, PerfPlugin.PLUGIN_ID,
e.getMessage());
PerfPlugin.getDefault().getLog().log(status);
}
}