Browse Source

added basic support for event data collected by Hook.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5195 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Siegfried Pammer 16 years ago
parent
commit
bc817ae3e0
  1. 7
      src/AddIns/Misc/Profiler/Controller/Data/IProfilingDataWriter.cs
  2. 30
      src/AddIns/Misc/Profiler/Controller/Data/PerformanceCounterDescriptor.cs
  3. 2
      src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataProvider.cs
  4. 24
      src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
  5. 62
      src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteWriter.cs
  6. 16
      src/AddIns/Misc/Profiler/Controller/Data/TempFileDatabase.cs
  7. 16
      src/AddIns/Misc/Profiler/Controller/Data/UnitTestRootCallTreeNode.cs
  8. 13
      src/AddIns/Misc/Profiler/Controller/Data/UnitTestWriter.cs
  9. 18
      src/AddIns/Misc/Profiler/Controller/Data/UnmanagedCallTreeNode.cs
  10. 1
      src/AddIns/Misc/Profiler/Controller/Profiler.Controller.csproj
  11. 15
      src/AddIns/Misc/Profiler/Controller/Profiler.cs
  12. 4
      src/AddIns/Misc/Profiler/Controller/ProfilerOptions.cs

7
src/AddIns/Misc/Profiler/Controller/Data/IProfilingDataWriter.cs

@ -31,6 +31,8 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -31,6 +31,8 @@ namespace ICSharpCode.Profiler.Controller.Data
void WritePerformanceCounterData(IEnumerable<PerformanceCounterDescriptor> counters);
void WriteEventData(IEnumerable<EventDataEntry> events);
/// <summary>
/// Closes and disposes the underlying data structure.
/// </summary>
@ -41,5 +43,10 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -41,5 +43,10 @@ namespace ICSharpCode.Profiler.Controller.Data
/// The processor frequency is measured in MHz.
/// </summary>
int ProcessorFrequency { get; set; }
/// <summary>
/// Gets the number of datasets that have been written by this IProfilingDataWriter.
/// </summary>
int DataSetCount { get; }
}
}

30
src/AddIns/Misc/Profiler/Controller/Data/PerformanceCounterDescriptor.cs

@ -23,12 +23,13 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -23,12 +23,13 @@ namespace ICSharpCode.Profiler.Controller.Data
public float? MinValue { get; private set; }
public float? MaxValue { get; private set; }
public string Unit { get; private set; }
public string Format { get; private set; }
float defaultValue;
PerformanceCounter counter;
public PerformanceCounterDescriptor(string category, string name, string instance, string computer,
float defaultValue, float? minValue, float? maxValue, string unit)
float defaultValue, float? minValue, float? maxValue, string unit, string format)
{
Category = category;
Name = name;
@ -39,10 +40,11 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -39,10 +40,11 @@ namespace ICSharpCode.Profiler.Controller.Data
MinValue = minValue;
MaxValue = maxValue;
Unit = unit;
Format = format;
}
public PerformanceCounterDescriptor(string name, float? minValue, float? maxValue, string unit)
: this(null, name, null, null, 0, minValue, maxValue, unit)
public PerformanceCounterDescriptor(string name, float? minValue, float? maxValue, string unit, string format)
: this(null, name, null, null, 0, minValue, maxValue, unit, format)
{
}
@ -52,8 +54,8 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -52,8 +54,8 @@ namespace ICSharpCode.Profiler.Controller.Data
string[] instances = cat.GetInstanceNames();
foreach (string instance in instances) {
using (PerformanceCounter cnt = new PerformanceCounter("Process", "ID Process", instance, true)) {
int val = (int)cnt.RawValue;
using (PerformanceCounter procIdCounter = new PerformanceCounter("Process", "ID Process", instance, true)) {
int val = (int)procIdCounter.RawValue;
if (val == pid)
return instance;
}
@ -75,7 +77,9 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -75,7 +77,9 @@ namespace ICSharpCode.Profiler.Controller.Data
try {
this.Values.Add(counter.NextValue());
} catch (Exception e) {
#if DEBUG
Console.WriteLine(e.ToString());
#endif
this.Values.Add(defaultValue);
}
}
@ -85,4 +89,20 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -85,4 +89,20 @@ namespace ICSharpCode.Profiler.Controller.Data
return Name;
}
}
public enum EventType : int
{
Exception = 0,
Console = 1,
WindowsForms = 2,
WindowsPresentationFoundation = 3
}
public class EventDataEntry
{
public int DataSetId { get; set; }
public EventType Type { get; set; }
public int NameId { get; set; }
public string Data { get; set; }
}
}

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

@ -80,5 +80,7 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -80,5 +80,7 @@ namespace ICSharpCode.Profiler.Controller.Data
public abstract PerformanceCounterDescriptor[] GetPerformanceCounters();
public abstract float[] GetPerformanceCounterValues(int index);
public abstract EventDataEntry[] GetEventDataEntries(int index);
}
}

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

@ -356,7 +356,7 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -356,7 +356,7 @@ namespace ICSharpCode.Profiler.Controller.Data
{
SQLiteCommand cmd;
using (LockAndCreateCommand(out cmd)) {
cmd.CommandText = "SELECT name, minvalue, maxvalue, unit " +
cmd.CommandText = "SELECT name, minvalue, maxvalue, unit, format " +
"FROM PerformanceCounter " +
"ORDER BY id ASC;";
@ -370,7 +370,8 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -370,7 +370,8 @@ namespace ICSharpCode.Profiler.Controller.Data
reader.GetString(0),
reader.IsDBNull(1) ? null : new Nullable<float>(reader.GetFloat(1)),
reader.IsDBNull(2) ? null : new Nullable<float>(reader.GetFloat(2)),
reader.GetString(3)
reader.GetString(3),
reader.GetString(4)
)
);
}
@ -399,6 +400,25 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -399,6 +400,25 @@ namespace ICSharpCode.Profiler.Controller.Data
}
}
public override EventDataEntry[] GetEventDataEntries(int index)
{
SQLiteCommand cmd;
using (LockAndCreateCommand(out cmd)) {
cmd.CommandText = "SELECT eventtype, nameid, data " +
"FROM EventData " +
"WHERE datasetid = " + index;
List<EventDataEntry> list = new List<EventDataEntry>();
var reader = cmd.ExecuteReader();
while (reader.Read())
list.Add(new EventDataEntry() { Data = reader.GetString(2), DataSetId = index, NameId = reader.GetInt32(1), Type = (EventType)reader.GetInt32(0) });
return list.ToArray();
}
}
Expression<Func<SingleCall, bool>> DataSetFilter(int startIndex, int endIndex)
{
return c => startIndex <= c.DataSetID && c.DataSetID <= endIndex;

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

@ -61,6 +61,9 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -61,6 +61,9 @@ namespace ICSharpCode.Profiler.Controller.Data
/// </summary>
public void Close()
{
if (isDisposed)
return;
using (SQLiteCommand cmd = this.connection.CreateCommand()) {
// create index at the end (after inserting data), this is faster
cmd.CommandText = CallsAndFunctionsIndexDefs;
@ -170,6 +173,7 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -170,6 +173,7 @@ namespace ICSharpCode.Profiler.Controller.Data
name TEXT NOT NULL,
minvalue REAL NULL,
maxvalue REAL NULL,
format TEXT NOT NULL,
unit TEXT NOT NULL
);
@ -178,6 +182,13 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -178,6 +182,13 @@ namespace ICSharpCode.Profiler.Controller.Data
counterid INTEGER NOT NULL,
value REAL NOT NULL
);
CREATE TABLE EventData(
datasetid INTEGER NOT NULL,
eventtype INTEGER NOT NULL,
nameid INTEGER NOT NULL,
data TEXT NULL
);
";
internal const string CallsAndFunctionsIndexDefs =
@ -239,19 +250,22 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -239,19 +250,22 @@ namespace ICSharpCode.Profiler.Controller.Data
InsertCalls(cmd, child, thisID, dataParams);
}
long cpuCycles = node.CpuCyclesSpent;
long cpuCyclesSelf = node.CpuCyclesSpentSelf;
// we sometimes saw invalid data with the 0x0080000000000000L bit set
if (node.CpuCyclesSpent > 0x0007ffffffffffffL || node.CpuCyclesSpent < 0) {
if (cpuCycles > 0x0007ffffffffffffL || cpuCycles < 0) {
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");
if (node.NameMapping.Id != 0 && (cpuCyclesSelf > cpuCycles || cpuCyclesSelf < 0)) {
throw new InvalidOperationException("Too large/small CpuCyclesSpentSelf (" + cpuCyclesSelf + ") - there's something wrong in the data");
}
dataParams.callCount.Value = node.RawCallCount;
dataParams.isActiveAtStart.Value = node.IsActiveAtStart;
dataParams.cpuCyclesSpent.Value = node.CpuCyclesSpent;
dataParams.cpuCyclesSpentSelf.Value = node.CpuCyclesSpentSelf;
dataParams.cpuCyclesSpent.Value = cpuCycles;
dataParams.cpuCyclesSpentSelf.Value = cpuCyclesSelf;
dataParams.functionInfoId.Value = thisID;
dataParams.nameId.Value = node.NameMapping.Id;
@ -302,6 +316,7 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -302,6 +316,7 @@ namespace ICSharpCode.Profiler.Controller.Data
isDisposed = true;
}
/// <inheritdoc/>
public void WritePerformanceCounterData(IEnumerable<PerformanceCounterDescriptor> counters)
{
using (SQLiteTransaction trans = this.connection.BeginTransaction()) {
@ -316,8 +331,8 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -316,8 +331,8 @@ namespace ICSharpCode.Profiler.Controller.Data
SQLiteParameter unitParam = new SQLiteParameter("unit");
cmd.CommandText =
"INSERT OR IGNORE INTO PerformanceCounter(id, name, minvalue, maxvalue, unit)" +
"VALUES(@id,@name,@min,@max,@unit);" +
"INSERT OR IGNORE INTO PerformanceCounter(id, name, minvalue, maxvalue, unit)" + // should I split these queries
"VALUES(@id,@name,@min,@max,@unit);" + // for better performance?
"INSERT INTO CounterData(datasetid, counterid, value)" +
"VALUES(@dataset,@id,@value);";
@ -344,5 +359,38 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -344,5 +359,38 @@ namespace ICSharpCode.Profiler.Controller.Data
trans.Commit();
}
}
/// <inheritdoc/>
public void WriteEventData(IEnumerable<EventDataEntry> events)
{
using (SQLiteTransaction trans = this.connection.BeginTransaction()) {
using (SQLiteCommand cmd = this.connection.CreateCommand()) {
SQLiteParameter dataSetParam = new SQLiteParameter("datasetid");
SQLiteParameter eventTypeParam = new SQLiteParameter("eventtype");
SQLiteParameter nameIdParam = new SQLiteParameter("nameid");
SQLiteParameter dataParam = new SQLiteParameter("data");
cmd.CommandText =
"INSERT INTO EventData(datasetid,eventtype,nameid,data) " +
"VALUES(@datasetid,@eventtype,@nameid,@data);";
cmd.Parameters.AddRange(new SQLiteParameter[] { dataSetParam, eventTypeParam, nameIdParam, dataParam });
foreach (EventDataEntry entry in events) {
dataSetParam.Value = entry.DataSetId;
eventTypeParam.Value = (int)entry.Type;
nameIdParam.Value = entry.NameId;
dataParam.Value = entry.Data;
cmd.ExecuteNonQuery();
}
}
trans.Commit();
}
}
/// <inheritdoc/>
public int DataSetCount {
get { return this.dataSetCount; }
}
}
}

16
src/AddIns/Misc/Profiler/Controller/Data/TempFileDatabase.cs

@ -43,6 +43,12 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -43,6 +43,12 @@ namespace ICSharpCode.Profiler.Controller.Data
get { return counters.AsReadOnly(); }
}
List<EventDataEntry> events = new List<EventDataEntry>();
public ReadOnlyCollection<EventDataEntry> Events {
get { return events.AsReadOnly(); }
}
struct StreamInfo
{
public TargetProcessPointer NativeStartPosition { get; set; }
@ -143,6 +149,15 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -143,6 +149,15 @@ namespace ICSharpCode.Profiler.Controller.Data
{
this.database.counters.AddRange(counters);
}
public void WriteEventData(IEnumerable<EventDataEntry> events)
{
this.database.events.AddRange(events);
}
public int DataSetCount {
get { return this.database.DataSetCount; }
}
}
#endregion
@ -229,6 +244,7 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -229,6 +244,7 @@ namespace ICSharpCode.Profiler.Controller.Data
writer.ProcessorFrequency = this.processorFrequency;
writer.WriteMappings(this.nameMappings.Values);
writer.WritePerformanceCounterData(this.counters);
writer.WriteEventData(this.events);
for (int i = 0; i < this.DataSetCount; i++) {
using (UnmanagedProfilingDataSet dataSet = this.LoadDataSet(i))

16
src/AddIns/Misc/Profiler/Controller/Data/UnitTestRootCallTreeNode.cs

@ -15,13 +15,14 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -15,13 +15,14 @@ namespace ICSharpCode.Profiler.Controller.Data
/// </summary>
public class UnitTestRootCallTreeNode : CallTreeNode
{
List<CallTreeNode> unitTests;
List<CallTreeNode> unitTests = null;
/// <summary>
/// Creates a new UnitTestRootCallTreeNode.
/// </summary>
public UnitTestRootCallTreeNode(IEnumerable<CallTreeNode> unitTests)
{
if (unitTests != null)
this.unitTests = new List<CallTreeNode>(unitTests);
}
@ -42,7 +43,7 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -42,7 +43,7 @@ namespace ICSharpCode.Profiler.Controller.Data
/// <inheritdoc/>
public override bool IsActiveAtStart {
get {
return this.unitTests.Any(test => test.IsActiveAtStart);
return (this.unitTests == null) ? false : this.unitTests.Any(test => test.IsActiveAtStart);
}
}
@ -77,14 +78,19 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -77,14 +78,19 @@ namespace ICSharpCode.Profiler.Controller.Data
/// <inheritdoc/>
public override int GetHashCode()
{
return this.unitTests.Aggregate(0, (sum, item) => sum ^= item.GetHashCode());
return (this.unitTests == null) ? 0 : this.unitTests.Aggregate(0, (sum, item) => sum ^= item.GetHashCode());
}
/// <inheritdoc/>
public override bool Equals(CallTreeNode other)
{
UnitTestRootCallTreeNode node = other as UnitTestRootCallTreeNode;
return node != null && node.unitTests.SequenceEqual(unitTests);
if (node != null && unitTests != null) {
return node.unitTests.SequenceEqual(unitTests);
}
return false;
}
/// <inheritdoc/>
@ -97,7 +103,7 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -97,7 +103,7 @@ namespace ICSharpCode.Profiler.Controller.Data
/// <inheritdoc/>
public override IQueryable<CallTreeNode> Children {
get {
return unitTests.AsQueryable();
return ((unitTests == null) ? Enumerable.Empty<CallTreeNode>() : unitTests).AsQueryable();
}
}

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

@ -69,6 +69,10 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -69,6 +69,10 @@ namespace ICSharpCode.Profiler.Controller.Data
this.targetWriter.WriteDataSet(
new UnitTestDataSet(new UnitTestRootCallTreeNode(list), dataSet.IsFirst)
);
} else {
this.targetWriter.WriteDataSet(
new UnitTestDataSet(new UnitTestRootCallTreeNode(null), dataSet.IsFirst)
);
}
}
@ -105,5 +109,14 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -105,5 +109,14 @@ namespace ICSharpCode.Profiler.Controller.Data
{
this.targetWriter.WritePerformanceCounterData(counters);
}
public void WriteEventData(IEnumerable<EventDataEntry> events)
{
this.targetWriter.WriteEventData(events);
}
public int DataSetCount {
get { return this.targetWriter.DataSetCount; }
}
}
}

18
src/AddIns/Misc/Profiler/Controller/Data/UnmanagedCallTreeNode.cs

@ -83,6 +83,24 @@ namespace ICSharpCode.Profiler.Controller.Data @@ -83,6 +83,24 @@ namespace ICSharpCode.Profiler.Controller.Data
}
}
public override long CpuCyclesSpentSelf {
get {
dataSet.VerifyAccess();
long result = (long)(this.data->TimeSpent & CpuCycleMask);
TargetProcessPointer32* childrenPtr = FunctionInfo.GetChildren32(data);
for (int i = 0; i <= data->LastChildIndex; i++)
{
FunctionInfo* child = dataSet.GetFunctionInfo(childrenPtr[i]);
if (child != null)
result -= (long)(child->TimeSpent & CpuCycleMask);
}
return result;
}
}
public override CallTreeNode Parent {
get {
return this.parent;

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

@ -89,7 +89,6 @@ @@ -89,7 +89,6 @@
<Reference Include="System.Data" />
<Reference Include="System.Data.SQLite">
<HintPath>..\..\..\..\Libraries\SQLite\System.Data.SQLite.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml" />
</ItemGroup>

15
src/AddIns/Misc/Profiler/Controller/Profiler.cs

@ -619,7 +619,6 @@ namespace ICSharpCode.Profiler.Controller @@ -619,7 +619,6 @@ namespace ICSharpCode.Profiler.Controller
isRunning = false;
this.dataWriter.WritePerformanceCounterData(performanceCounters);
this.dataWriter.Close();
OnSessionEnded(EventArgs.Empty);
@ -703,10 +702,22 @@ namespace ICSharpCode.Profiler.Controller @@ -703,10 +702,22 @@ namespace ICSharpCode.Profiler.Controller
string name = parts[3] + ((string.IsNullOrEmpty(parts[4])) ? "" : " - " + parts[4]);
lock (this.dataWriter) {
this.dataWriter.WriteMappings(new NameMapping[] {new NameMapping(id, null, name, null)});
this.dataWriter.WriteMappings(new[] {new NameMapping(id, null, name, null)});
}
return true;
} else if (readString.StartsWith("event ", StringComparison.Ordinal)) {
string[] parts = readString.Split(' ');
// event <typeid> <nameid> <data>
if (parts.Length != 4)
return false;
int type = int.Parse(parts[1], CultureInfo.InvariantCulture);
int name = int.Parse(parts[2], CultureInfo.InvariantCulture);
string data = parts[3];
lock (this.dataWriter) {
this.dataWriter.WriteEventData(new[] { new EventDataEntry() { DataSetId = this.dataWriter.DataSetCount, NameId = name, Type = (EventType)type, Data = data } });
}
} else {
if (readString.StartsWith("error-", StringComparison.Ordinal)) {
string[] parts = readString.Split('-');

4
src/AddIns/Misc/Profiler/Controller/ProfilerOptions.cs

@ -25,8 +25,8 @@ namespace ICSharpCode.Profiler.Controller @@ -25,8 +25,8 @@ namespace ICSharpCode.Profiler.Controller
public const int DefaultSharedMemorySize = 64 * 1024 * 1024; // 64 mb
public static readonly PerformanceCounterDescriptor[] DefaultCounters = new[] {
new PerformanceCounterDescriptor("Process", "% Processor Time", "_Total", ".", 0, 0, 100, "%"),
new PerformanceCounterDescriptor("Process", "IO Data Bytes/sec", "_Total", ".", 0, null, null, "bytes/sec")
new PerformanceCounterDescriptor("Process", "% Processor Time", "_Total", ".", 0, 0, 100, "%", "0.00"),
new PerformanceCounterDescriptor("Process", "IO Data Bytes/sec", "_Total", ".", 0, null, null, "bytes/sec", "#,##0")
};
bool enableDC;

Loading…
Cancel
Save