Browse Source

Profiler:

- updated ProfilingDataSQLiteWriter to create SDPS 1.1
- extracted unit test specific writer code to UnitTestWriter
- added cpuCyclesSpentSelf in database

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5039 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 16 years ago
parent
commit
ebe54fa166
  1. 2
      src/AddIns/Misc/Profiler/Controller/Data/CallTreeNode.cs
  2. 1
      src/AddIns/Misc/Profiler/Controller/Data/Linq/AllCalls.cs
  3. 1
      src/AddIns/Misc/Profiler/Controller/Data/Linq/AllFunctions.cs
  4. 1
      src/AddIns/Misc/Profiler/Controller/Data/Linq/MergeByName.cs
  5. 1
      src/AddIns/Misc/Profiler/Controller/Data/Linq/QueryNode.cs
  6. 2
      src/AddIns/Misc/Profiler/Controller/Data/Linq/SqlQueryContext.cs
  7. 10
      src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
  8. 129
      src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteWriter.cs
  9. 6
      src/AddIns/Misc/Profiler/Controller/Data/SQLiteCallTreeNode.cs
  10. 98
      src/AddIns/Misc/Profiler/Controller/Data/UnitTestWriter.cs
  11. 1
      src/AddIns/Misc/Profiler/Controller/Profiler.Controller.csproj
  12. 2
      src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/ProfileProject.cs
  13. 2
      src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/RunTestWithProfilerCommand.cs
  14. 2
      src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Dialogs/ProfileExecutableForm.xaml.cs
  15. 2
      src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/Data/LinqTests.cs

2
src/AddIns/Misc/Profiler/Controller/Data/CallTreeNode.cs

@ -84,7 +84,7 @@ namespace ICSharpCode.Profiler.Controller.Data
/// </summary> /// </summary>
public virtual long CpuCyclesSpentSelf { public virtual long CpuCyclesSpentSelf {
get { get {
return CpuCyclesSpent - Children.Aggregate(0L, (sum, item) => sum + item.CpuCyclesSpent); return CpuCyclesSpent - Children.Sum(item => item.CpuCyclesSpent);
} }
} }

1
src/AddIns/Misc/Profiler/Controller/Data/Linq/AllCalls.cs

@ -49,6 +49,7 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
b.AppendLine("SELECT " b.AppendLine("SELECT "
+ SqlAs("nameid", newNames.NameID) + ", " + SqlAs("nameid", newNames.NameID) + ", "
+ SqlAs("cpucyclesspent", newNames.CpuCyclesSpent) + ", " + SqlAs("cpucyclesspent", newNames.CpuCyclesSpent) + ", "
+ SqlAs("cpucyclesspentself", newNames.CpuCyclesSpentSelf) + ", "
+ SqlAs("callcount", newNames.CallCount) + ", " + SqlAs("callcount", newNames.CallCount) + ", "
+ SqlAs("(id != endid)", newNames.HasChildren) + ", " + SqlAs("(id != endid)", newNames.HasChildren) + ", "
+ SqlAs("((id BETWEEN " + context.StartDataSet.RootID + " AND " + context.StartDataSet.CallEndID + SqlAs("((id BETWEEN " + context.StartDataSet.RootID + " AND " + context.StartDataSet.CallEndID

1
src/AddIns/Misc/Profiler/Controller/Data/Linq/AllFunctions.cs

@ -56,6 +56,7 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
b.AppendLine("SELECT " b.AppendLine("SELECT "
+ SqlAs("nameid", newNames.NameID) + ", " + SqlAs("nameid", newNames.NameID) + ", "
+ SqlAs("SUM(cpucyclesspent)", newNames.CpuCyclesSpent) + ", " + SqlAs("SUM(cpucyclesspent)", newNames.CpuCyclesSpent) + ", "
+ SqlAs("SUM(cpucyclesspentself)", newNames.CpuCyclesSpentSelf) + ", "
+ SqlAs("SUM(callcount)", newNames.CallCount) + ", " + SqlAs("SUM(callcount)", newNames.CallCount) + ", "
+ SqlAs("MAX(hasChildren)", newNames.HasChildren) + ", " + SqlAs("MAX(hasChildren)", newNames.HasChildren) + ", "
+ SqlAs("SUM(CASE WHEN datasetid = " + context.StartDataSet.ID + " THEN activecallcount ELSE 0 END)", newNames.ActiveCallCount)); + SqlAs("SUM(CASE WHEN datasetid = " + context.StartDataSet.ID + " THEN activecallcount ELSE 0 END)", newNames.ActiveCallCount));

1
src/AddIns/Misc/Profiler/Controller/Data/Linq/MergeByName.cs

@ -53,6 +53,7 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
string query = "SELECT " string query = "SELECT "
+ SqlAs(oldNames.NameID, newNames.NameID) + ", " + SqlAs(oldNames.NameID, newNames.NameID) + ", "
+ SqlAs("SUM(" + oldNames.CpuCyclesSpent + ")", newNames.CpuCyclesSpent) + ", " + SqlAs("SUM(" + oldNames.CpuCyclesSpent + ")", newNames.CpuCyclesSpent) + ", "
+ SqlAs("SUM(" + oldNames.CpuCyclesSpentSelf + ")", newNames.CpuCyclesSpentSelf) + ", "
+ SqlAs("SUM(" + oldNames.CallCount + ")", newNames.CallCount) + ", " + SqlAs("SUM(" + oldNames.CallCount + ")", newNames.CallCount) + ", "
+ SqlAs("MAX(" + oldNames.HasChildren + ")", newNames.HasChildren) + ", " + SqlAs("MAX(" + oldNames.HasChildren + ")", newNames.HasChildren) + ", "
+ SqlAs("SUM(" + oldNames.ActiveCallCount + ")", newNames.ActiveCallCount); + SqlAs("SUM(" + oldNames.ActiveCallCount + ")", newNames.ActiveCallCount);

1
src/AddIns/Misc/Profiler/Controller/Data/Linq/QueryNode.cs

@ -87,6 +87,7 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
string query = "SELECT " string query = "SELECT "
+ SqlAs(oldNames.NameID, newNames.NameID) + ", " + SqlAs(oldNames.NameID, newNames.NameID) + ", "
+ SqlAs(oldNames.CpuCyclesSpent, newNames.CpuCyclesSpent) + ", " + SqlAs(oldNames.CpuCyclesSpent, newNames.CpuCyclesSpent) + ", "
+ SqlAs(oldNames.CpuCyclesSpentSelf, newNames.CpuCyclesSpentSelf) + ", "
+ SqlAs(oldNames.CallCount, newNames.CallCount) + ", " + SqlAs(oldNames.CallCount, newNames.CallCount) + ", "
+ SqlAs(oldNames.HasChildren, newNames.HasChildren) + ", " + SqlAs(oldNames.HasChildren, newNames.HasChildren) + ", "
+ SqlAs(oldNames.ActiveCallCount, newNames.ActiveCallCount); + SqlAs(oldNames.ActiveCallCount, newNames.ActiveCallCount);

2
src/AddIns/Misc/Profiler/Controller/Data/Linq/SqlQueryContext.cs

@ -79,6 +79,7 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
public readonly string ID; public readonly string ID;
public readonly string NameID; public readonly string NameID;
public readonly string CpuCyclesSpent; public readonly string CpuCyclesSpent;
public readonly string CpuCyclesSpentSelf;
public readonly string CallCount; public readonly string CallCount;
public readonly string HasChildren; public readonly string HasChildren;
public readonly string ActiveCallCount; public readonly string ActiveCallCount;
@ -89,6 +90,7 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
ID = prefix + "ID"; ID = prefix + "ID";
NameID = prefix + "NameID"; NameID = prefix + "NameID";
CpuCyclesSpent = prefix + "CpuCyclesSpent"; CpuCyclesSpent = prefix + "CpuCyclesSpent";
CpuCyclesSpentSelf = prefix + "CpuCyclesSpentSelf";
CallCount = prefix + "CallCount"; CallCount = prefix + "CallCount";
HasChildren = prefix + "HasChildren"; HasChildren = prefix + "HasChildren";
ActiveCallCount = prefix + "ActiveCallCount"; ActiveCallCount = prefix + "ActiveCallCount";

10
src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs

@ -43,7 +43,6 @@ namespace ICSharpCode.Profiler.Controller.Data
this.connection = new SQLiteConnection(conn.ConnectionString); this.connection = new SQLiteConnection(conn.ConnectionString);
try { try {
this.connection.Open(); this.connection.Open();
CheckFileVersion(allowUpgrade); CheckFileVersion(allowUpgrade);
@ -365,10 +364,11 @@ namespace ICSharpCode.Profiler.Controller.Data
using (SQLiteDataReader reader = cmd.ExecuteReader()) { using (SQLiteDataReader reader = cmd.ExecuteReader()) {
while (reader.Read()) { while (reader.Read()) {
SQLiteCallTreeNode node = new SQLiteCallTreeNode(reader.GetInt32(0), null, queryProvider); SQLiteCallTreeNode node = new SQLiteCallTreeNode(reader.GetInt32(0), null, queryProvider);
node.callCount = reader.GetInt32(2); node.callCount = reader.GetInt32(3);
node.cpuCyclesSpent = reader.GetInt64(1); node.cpuCyclesSpent = reader.GetInt64(1);
node.cpuCyclesSpentSelf = reader.GetInt64(2);
if (hasIdList) { if (hasIdList) {
object ids = reader.GetValue(5); object ids = reader.GetValue(6);
if (ids is long) { if (ids is long) {
node.IdList = new int[] { (int)(long)ids }; node.IdList = new int[] { (int)(long)ids };
} else { } else {
@ -377,8 +377,8 @@ namespace ICSharpCode.Profiler.Controller.Data
node.IdList = idList; node.IdList = idList;
} }
} }
node.hasChildren = reader.GetBoolean(3); node.hasChildren = reader.GetBoolean(4);
node.activeCallCount = reader.GetInt32(4); node.activeCallCount = reader.GetInt32(5);
result.Add(node); result.Add(node);
} }
} }

129
src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteWriter.cs

@ -30,13 +30,11 @@ namespace ICSharpCode.Profiler.Controller.Data
int functionInfoCount; int functionInfoCount;
bool isDisposed; bool isDisposed;
int processorFrequency; int processorFrequency;
bool profileUnitTests;
string[] unitTestNames;
/// <summary> /// <summary>
/// Creates a new SQLite profiling data provider and opens or creates a new database stored in a file. /// Creates a new SQLite profiling data provider and opens or creates a new database stored in a file.
/// </summary> /// </summary>
public ProfilingDataSQLiteWriter(string fileName, bool profileUnitTests, string[] unitTestNames) public ProfilingDataSQLiteWriter(string fileName)
{ {
if (File.Exists(fileName)) if (File.Exists(fileName))
throw new IOException("File already exists!"); throw new IOException("File already exists!");
@ -56,12 +54,6 @@ namespace ICSharpCode.Profiler.Controller.Data
InitializeTables(); InitializeTables();
File.SetAttributes(fileName, FileAttributes.Compressed); File.SetAttributes(fileName, FileAttributes.Compressed);
this.profileUnitTests = profileUnitTests;
this.unitTestNames = unitTestNames;
if (profileUnitTests && unitTestNames == null)
throw new InvalidOperationException("Please add unit tests to filter!");
} }
/// <summary> /// <summary>
@ -71,11 +63,7 @@ namespace ICSharpCode.Profiler.Controller.Data
{ {
using (SQLiteCommand cmd = this.connection.CreateCommand()) { using (SQLiteCommand cmd = this.connection.CreateCommand()) {
// create index at the end (after inserting data), this is faster // create index at the end (after inserting data), this is faster
cmd.CommandText = @"CREATE INDEX Parents ON FunctionData(parentid ASC);"; cmd.CommandText = CallsAndFunctionsIndexDefs;
cmd.ExecuteNonQuery();
// make SQLite analyze the indices available; this will help the query planner later
cmd.CommandText = @"ANALYZE;";
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
@ -118,70 +106,45 @@ namespace ICSharpCode.Profiler.Controller.Data
cmd.CommandText = "INSERT INTO DataSets(id, cpuusage, isfirst, rootid)" + cmd.CommandText = "INSERT INTO DataSets(id, cpuusage, isfirst, rootid)" +
"VALUES(?,?,?,?);"; "VALUES(?,?,?,?);";
int dataSetStartId = functionInfoCount;
using (SQLiteCommand loopCommand = this.connection.CreateCommand()) { using (SQLiteCommand loopCommand = this.connection.CreateCommand()) {
CallTreeNode node = dataSet.RootNode; CallTreeNode node = dataSet.RootNode;
loopCommand.CommandText = "INSERT INTO FunctionData(datasetid, id, endid, parentid, nameid, timespent, isactiveatstart, callcount)" + loopCommand.CommandText = "INSERT INTO Calls(id, endid, parentid, nameid, cpucyclesspent, cpucyclesspentself, isactiveatstart, callcount)" +
"VALUES(?,?,?,?,?,?,?,?);"; "VALUES(?,?,?,?,?,?,?,?);";
FunctionDataParams dataParams = new FunctionDataParams(); CallsParams dataParams = new CallsParams();
loopCommand.Parameters.Add(dataParams.dataSetId = new SQLiteParameter());
loopCommand.Parameters.Add(dataParams.functionInfoId = new SQLiteParameter()); loopCommand.Parameters.Add(dataParams.functionInfoId = new SQLiteParameter());
loopCommand.Parameters.Add(dataParams.endId = new SQLiteParameter()); loopCommand.Parameters.Add(dataParams.endId = new SQLiteParameter());
loopCommand.Parameters.Add(dataParams.parentId = new SQLiteParameter()); loopCommand.Parameters.Add(dataParams.parentId = new SQLiteParameter());
loopCommand.Parameters.Add(dataParams.nameId = new SQLiteParameter()); loopCommand.Parameters.Add(dataParams.nameId = new SQLiteParameter());
loopCommand.Parameters.Add(dataParams.cpuCyclesSpent = new SQLiteParameter()); loopCommand.Parameters.Add(dataParams.cpuCyclesSpent = new SQLiteParameter());
loopCommand.Parameters.Add(dataParams.cpuCyclesSpentSelf = new SQLiteParameter());
loopCommand.Parameters.Add(dataParams.isActiveAtStart = new SQLiteParameter()); loopCommand.Parameters.Add(dataParams.isActiveAtStart = new SQLiteParameter());
loopCommand.Parameters.Add(dataParams.callCount = new SQLiteParameter()); loopCommand.Parameters.Add(dataParams.callCount = new SQLiteParameter());
InsertCalls(loopCommand, node, -1, dataParams);
}
using (SQLiteCommand functionsCommand = this.connection.CreateCommand()) {
functionsCommand.CommandText = string.Format(@"
INSERT INTO Functions
SELECT {0}, nameid, SUM(cpucyclesspent), SUM(cpucyclesspentself), SUM(isactiveatstart), SUM(callcount), MAX(id != endid)
FROM Calls
WHERE id BETWEEN {1} AND {2}
GROUP BY nameid;", dataSetCount, dataSetStartId, functionInfoCount - 1);
bool addedData = true; functionsCommand.ExecuteNonQuery();
if (profileUnitTests)
addedData = FindUnitTestsAndInsert(loopCommand, node, dataSet, dataParams);
else
InsertTree(loopCommand, node, -1, dataSet, dataParams);
if (addedData) {
cmd.ExecuteNonQuery();
dataSetCount++;
}
} }
cmd.ExecuteNonQuery();
dataSetCount++;
transaction.Commit(); transaction.Commit();
} }
} }
bool IsUnitTest(NameMapping name)
{
return unitTestNames.Contains(name.Name);
}
bool FindUnitTestsAndInsert(SQLiteCommand cmd, CallTreeNode node, IProfilingDataSet dataSet, FunctionDataParams dataParams)
{
List<CallTreeNode> list = new List<CallTreeNode>();
FindUnitTests(node, list);
if (list.Count > 0) {
InsertTree(cmd, new UnitTestRootCallTreeNode(list), -1, dataSet, dataParams);
return true;
}
return false;
}
void FindUnitTests(CallTreeNode parentNode, IList<CallTreeNode> list)
{
if (IsUnitTest(parentNode.NameMapping)) {
list.Add(parentNode);
return;
}
foreach (var node in parentNode.Children) {
FindUnitTests(node, list);
}
}
internal const string CallsAndFunctionsTableDefs = @" internal const string CallsAndFunctionsTableDefs = @"
CREATE TABLE Calls ( CREATE TABLE Calls (
id INTEGER NOT NULL PRIMARY KEY, id INTEGER NOT NULL PRIMARY KEY,
@ -202,24 +165,25 @@ namespace ICSharpCode.Profiler.Controller.Data
callcount INTEGER NOT NULL, callcount INTEGER NOT NULL,
hasChildren INTEGER NOT NULL hasChildren INTEGER NOT NULL
);"; );";
internal const string CallsAndFunctionsIndexDefs = internal const string CallsAndFunctionsIndexDefs =
"CREATE INDEX CallsParent ON Calls(parentid ASC);" // required for searching the children "CREATE INDEX CallsParent ON Calls(parentid ASC);" // required for searching the children
+ " ANALYZE;"; // make SQLite analyze the indices available; this will help the query planner later + " ANALYZE;"; // make SQLite analyze the indices available; this will help the query planner later
void InitializeTables() void InitializeTables()
{ {
//NameMapping { Id, ReturnType, Name, Parameters } // NameMapping { Id, ReturnType, Name, Parameters }
// TODO : update db schema: change FunctionData.TimeSpent to cpucyclesspent // Calls { id, endid, parentid, nameid, cpucyclesspent, cpucyclesspentself, isactiveatstart, callcount }
//FunctionData { DataSetId, Id, ParentId, NameId, TimeSpent, CallCount } // Functions { datasetid, nameid, cpucyclesspent, cpucyclesspentself, activecallcount, callcount, haschildren }
//DataSets { Id, CPUUsage, RootId } // DataSets { Id, CPUUsage, RootId }
// //
//NameMapping.Id <-> FunctionData.NameId 1:N // NameMapping.Id <-> FunctionData.NameId 1:N
//FunctionData.ParentId <-> FunctionData.Id 1:N // FunctionData.ParentId <-> FunctionData.Id 1:N
SQLiteCommand cmd = this.connection.CreateCommand(); SQLiteCommand cmd = this.connection.CreateCommand();
cmd.CommandText = @" cmd.CommandText = CallsAndFunctionsTableDefs + @"
CREATE TABLE NameMapping( CREATE TABLE NameMapping(
id INTEGER NOT NULL PRIMARY KEY, id INTEGER NOT NULL PRIMARY KEY,
returntype TEXT NOT NULL, returntype TEXT NOT NULL,
@ -227,16 +191,7 @@ namespace ICSharpCode.Profiler.Controller.Data
parameters TEXT NOT NULL parameters TEXT NOT NULL
); );
CREATE TABLE FunctionData( /* for CREATE TABLE of Calls and Functions see CallsAndFunctionsTableDefs */
datasetid INTEGER NOT NULL,
id INTEGER NOT NULL PRIMARY KEY,
endid INTEGER NOT NULL,
parentid INTEGER NOT NULL,
nameid INTEGER NOT NULL,
timespent INT8 NOT NULL,
isactiveatstart INTEGER NOT NULL,
callcount INTEGER NOT NULL
);
CREATE TABLE DataSets( CREATE TABLE DataSets(
id INTEGER NOT NULL PRIMARY KEY, id INTEGER NOT NULL PRIMARY KEY,
@ -250,7 +205,7 @@ namespace ICSharpCode.Profiler.Controller.Data
value TEXT NOT NULL value TEXT NOT NULL
); );
INSERT INTO Properties(name, value) VALUES('version', '1.0'); INSERT INTO Properties(name, value) VALUES('version', '1.1');
CREATE TABLE PerformanceCounter( CREATE TABLE PerformanceCounter(
id INTEGER NOT NULL PRIMARY KEY, id INTEGER NOT NULL PRIMARY KEY,
@ -267,18 +222,19 @@ namespace ICSharpCode.Profiler.Controller.Data
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
class FunctionDataParams class CallsParams
{ {
public SQLiteParameter dataSetId, functionInfoId, public SQLiteParameter functionInfoId,
parentId, nameId, cpuCyclesSpent, isActiveAtStart, callCount, endId; parentId, nameId, cpuCyclesSpent, cpuCyclesSpentSelf,
isActiveAtStart, callCount, endId;
} }
void InsertTree(SQLiteCommand cmd, CallTreeNode node, int parentId, IProfilingDataSet dataSet, FunctionDataParams dataParams) void InsertCalls(SQLiteCommand cmd, CallTreeNode node, int parentId, CallsParams dataParams)
{ {
int thisID = functionInfoCount++; int thisID = functionInfoCount++;
foreach (CallTreeNode child in node.Children) { foreach (CallTreeNode child in node.Children) {
InsertTree(cmd, child, thisID, dataSet, dataParams); InsertCalls(cmd, child, thisID, dataParams);
} }
// we sometimes saw invalid data with the 0x0080000000000000L bit set // we sometimes saw invalid data with the 0x0080000000000000L bit set
@ -286,10 +242,15 @@ namespace ICSharpCode.Profiler.Controller.Data
throw new InvalidOperationException("Too large CpuCyclesSpent - there's something wrong in the data"); throw new InvalidOperationException("Too large CpuCyclesSpent - there's something wrong in the data");
} }
if (node.NameMapping.Id != 0 && (node.CpuCyclesSpentSelf > node.CpuCyclesSpent || node.CpuCyclesSpentSelf < 0)) {
throw new InvalidOperationException("Too large/small CpuCyclesSpentSelf (" + node.CpuCyclesSpentSelf + ") - there's something wrong in the data");
}
dataParams.callCount.Value = node.RawCallCount; dataParams.callCount.Value = node.RawCallCount;
dataParams.isActiveAtStart.Value = node.IsActiveAtStart; dataParams.isActiveAtStart.Value = node.IsActiveAtStart;
dataParams.cpuCyclesSpent.Value = node.CpuCyclesSpent; dataParams.cpuCyclesSpent.Value = node.CpuCyclesSpent;
dataParams.dataSetId.Value = dataSetCount; dataParams.cpuCyclesSpentSelf.Value = node.CpuCyclesSpentSelf;
dataParams.functionInfoId.Value = thisID; dataParams.functionInfoId.Value = thisID;
dataParams.nameId.Value = node.NameMapping.Id; dataParams.nameId.Value = node.NameMapping.Id;
dataParams.parentId.Value = parentId; dataParams.parentId.Value = parentId;

6
src/AddIns/Misc/Profiler/Controller/Data/SQLiteCallTreeNode.cs

@ -24,6 +24,7 @@ namespace ICSharpCode.Profiler.Controller.Data
internal int nameId; internal int nameId;
internal int callCount; internal int callCount;
internal long cpuCyclesSpent; internal long cpuCyclesSpent;
internal long cpuCyclesSpentSelf;
CallTreeNode parent; CallTreeNode parent;
SQLiteQueryProvider provider; SQLiteQueryProvider provider;
internal bool hasChildren; internal bool hasChildren;
@ -88,7 +89,7 @@ namespace ICSharpCode.Profiler.Controller.Data
} }
public override long CpuCyclesSpentSelf { public override long CpuCyclesSpentSelf {
get { return 0; } get { return this.cpuCyclesSpentSelf; }
} }
/// <summary> /// <summary>
@ -133,7 +134,7 @@ namespace ICSharpCode.Profiler.Controller.Data
return CpuCyclesSpentSelf / (1000.0 * this.provider.ProcessorFrequency); return CpuCyclesSpentSelf / (1000.0 * this.provider.ProcessorFrequency);
} }
} }
/// <summary> /// <summary>
/// Gets whether the function call started in a previous data set that's not selected. /// Gets whether the function call started in a previous data set that's not selected.
/// </summary> /// </summary>
@ -163,6 +164,7 @@ namespace ICSharpCode.Profiler.Controller.Data
mergedNode.callCount += node.callCount; mergedNode.callCount += node.callCount;
mergedNode.cpuCyclesSpent += node.cpuCyclesSpent; mergedNode.cpuCyclesSpent += node.cpuCyclesSpent;
mergedNode.cpuCyclesSpentSelf += node.cpuCyclesSpentSelf;
mergedNode.activeCallCount += node.activeCallCount; mergedNode.activeCallCount += node.activeCallCount;
mergedNode.hasChildren |= node.hasChildren; mergedNode.hasChildren |= node.hasChildren;
if (!initialised || mergedNode.nameId == node.nameId) if (!initialised || mergedNode.nameId == node.nameId)

98
src/AddIns/Misc/Profiler/Controller/Data/UnitTestWriter.cs

@ -0,0 +1,98 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Siegfried Pammer" email="siegfriedpammer@gmail.com" />
// <version>$Revision$</version>
// </file>
using System;
using System.Linq;
using System.Collections.Generic;
namespace ICSharpCode.Profiler.Controller.Data
{
/// <summary>
/// Description of UnitTestWriter.
/// </summary>
public class UnitTestWriter : IProfilingDataWriter
{
IProfilingDataWriter targetWriter;
string[] unitTestNames;
public UnitTestWriter(IProfilingDataWriter targetWriter, string[] unitTestNames)
{
if (targetWriter == null)
throw new ArgumentNullException("targetWriter");
if (unitTestNames == null)
throw new ArgumentNullException("unitTestNames");
this.targetWriter = targetWriter;
this.unitTestNames = unitTestNames;
}
sealed class UnitTestDataSet : IProfilingDataSet
{
public UnitTestDataSet(CallTreeNode root, bool isFirst, double cpuUsage)
{
this.RootNode = root;
this.IsFirst = isFirst;
this.CpuUsage = cpuUsage;
}
public double CpuUsage { get; private set; }
public bool IsFirst { get; private set; }
public CallTreeNode RootNode { get; private set; }
}
public int ProcessorFrequency {
get { return this.targetWriter.ProcessorFrequency; }
set { this.targetWriter.ProcessorFrequency = value; }
}
public void WriteDataSet(IProfilingDataSet dataSet)
{
if (dataSet == null)
throw new ArgumentNullException("dataSet");
List<CallTreeNode> list = new List<CallTreeNode>();
FindUnitTests(dataSet.RootNode, list);
if (list.Count > 0) {
this.targetWriter.WriteDataSet(
new UnitTestDataSet(new UnitTestRootCallTreeNode(list), dataSet.IsFirst, dataSet.CpuUsage)
);
}
}
bool IsUnitTest(NameMapping name)
{
return unitTestNames.Contains(name.Name);
}
void FindUnitTests(CallTreeNode parentNode, IList<CallTreeNode> list)
{
if (IsUnitTest(parentNode.NameMapping)) {
list.Add(parentNode);
return;
}
foreach (var node in parentNode.Children) {
FindUnitTests(node, list);
}
}
public void WriteMappings(System.Collections.Generic.IEnumerable<NameMapping> mappings)
{
this.targetWriter.WriteMappings(mappings);
}
public void Close()
{
this.targetWriter.Close();
}
}
}

1
src/AddIns/Misc/Profiler/Controller/Profiler.Controller.csproj

@ -120,6 +120,7 @@
<Compile Include="Data\SQLiteCallTreeNode.cs" /> <Compile Include="Data\SQLiteCallTreeNode.cs" />
<Compile Include="Data\TempFileDatabase.cs" /> <Compile Include="Data\TempFileDatabase.cs" />
<Compile Include="Data\UnitTestRootCallTreeNode.cs" /> <Compile Include="Data\UnitTestRootCallTreeNode.cs" />
<Compile Include="Data\UnitTestWriter.cs" />
<Compile Include="Data\UnmanagedCallTreeNode.cs" /> <Compile Include="Data\UnmanagedCallTreeNode.cs" />
<Compile Include="Data\UnmanagedCallTreeNode64.cs"> <Compile Include="Data\UnmanagedCallTreeNode64.cs">
<DependentUpon>UnmanagedCallTreeNode.cs</DependentUpon> <DependentUpon>UnmanagedCallTreeNode.cs</DependentUpon>

2
src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/ProfileProject.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.Profiler.AddIn.Commands
string path = currentProj.GetSessionFileName(); string path = currentProj.GetSessionFileName();
Directory.CreateDirectory(Path.GetDirectoryName(path)); Directory.CreateDirectory(Path.GetDirectoryName(path));
IProfilingDataWriter writer = new ProfilingDataSQLiteWriter(path, false, null); IProfilingDataWriter writer = new ProfilingDataSQLiteWriter(path);
ProfilerRunner runner = ProfilerRunner.CreateRunner(writer); ProfilerRunner runner = ProfilerRunner.CreateRunner(writer);
if (runner != null) { if (runner != null) {

2
src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Commands/RunTestWithProfilerCommand.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.Profiler.AddIn.Commands
startInfo.WorkingDirectory = UnitTestApplicationStartHelper.UnitTestApplicationDirectory; startInfo.WorkingDirectory = UnitTestApplicationStartHelper.UnitTestApplicationDirectory;
LoggingService.Info("starting profiler..."); LoggingService.Info("starting profiler...");
runner = new ProfilerRunner(startInfo, true, new ProfilingDataSQLiteWriter(path, true, GetUnitTestNames(helper).ToArray())); runner = new ProfilerRunner(startInfo, true, new UnitTestWriter(new ProfilingDataSQLiteWriter(path), GetUnitTestNames(helper).ToArray()));
runner.RunFinished += delegate { runner.RunFinished += delegate {
WorkbenchSingleton.SafeThreadCall(() => FileService.OpenFile(path)); WorkbenchSingleton.SafeThreadCall(() => FileService.OpenFile(path));

2
src/AddIns/Misc/Profiler/Frontend/AddIn/Src/Dialogs/ProfileExecutableForm.xaml.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Profiler.AddIn.Dialogs
try { try {
Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
var runner = CreateRunner(txtExePath.Text, txtWorkingDir.Text, txtArgs.Text, new ProfilingDataSQLiteWriter(outputPath, false, null)); var runner = CreateRunner(txtExePath.Text, txtWorkingDir.Text, txtArgs.Text, new ProfilingDataSQLiteWriter(outputPath));
if (runner != null) { if (runner != null) {
runner.RunFinished += delegate { runner.RunFinished += delegate {

2
src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/Data/LinqTests.cs

@ -33,7 +33,7 @@ namespace Profiler.Tests.Controller.Data
NameMapping method0 = new NameMapping(0, "r0", "m0", new List<string>()); NameMapping method0 = new NameMapping(0, "r0", "m0", new List<string>());
NameMapping method1 = new NameMapping(1, "r1", "m1", new List<string>()); NameMapping method1 = new NameMapping(1, "r1", "m1", new List<string>());
NameMapping method2 = new NameMapping(2, "r2", "m2", new List<string>()); NameMapping method2 = new NameMapping(2, "r2", "m2", new List<string>());
using (var writer = new ProfilingDataSQLiteWriter(databaseFileName, false, null)) { using (var writer = new ProfilingDataSQLiteWriter(databaseFileName)) {
writer.ProcessorFrequency = 2000; // MHz writer.ProcessorFrequency = 2000; // MHz
writer.WriteMappings(new[] { method0, method1, method2 } ); writer.WriteMappings(new[] { method0, method1, method2 } );
CallTreeNodeStub dataSet; CallTreeNodeStub dataSet;

Loading…
Cancel
Save