|
|
|
@ -60,35 +60,11 @@ namespace ICSharpCode.Profiler.Controller.Data
@@ -60,35 +60,11 @@ namespace ICSharpCode.Profiler.Controller.Data
|
|
|
|
|
|
|
|
|
|
internal IQueryable<CallTreeNode> GetChildren(SQLiteCallTreeNode parent) |
|
|
|
|
{ |
|
|
|
|
SQLiteCommand cmd; |
|
|
|
|
using (LockAndCreateCommand(out cmd)) { |
|
|
|
|
cmd.CommandText = @"SELECT id, nameid, callcount, timespent, isactiveatstart
|
|
|
|
|
FROM FunctionData |
|
|
|
|
WHERE parentid IN(" + string.Join(",", parent.ids.Select(a => a.ToString(CultureInfo.InvariantCulture.NumberFormat)).ToArray()) + @") |
|
|
|
|
ORDER BY id;";
|
|
|
|
|
|
|
|
|
|
using (SQLiteDataReader reader = cmd.ExecuteReader()) { |
|
|
|
|
List<SQLiteCallTreeNode> items = new List<SQLiteCallTreeNode>(); |
|
|
|
|
|
|
|
|
|
while (reader.Read()) { |
|
|
|
|
int childNameId = reader.GetInt32(1); |
|
|
|
|
SQLiteCallTreeNode newItem = items.Find(node => node.nameId == childNameId); |
|
|
|
|
if (newItem == null) { |
|
|
|
|
newItem = new SQLiteCallTreeNode(childNameId, (parent.nameId == 0) ? null : parent, this); |
|
|
|
|
items.Add(newItem); |
|
|
|
|
|
|
|
|
|
// works because of ORDER BY id
|
|
|
|
|
newItem.isActiveAtStart = reader.GetBoolean(4); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
newItem.callCount += reader.GetInt32(2); |
|
|
|
|
newItem.cpuCyclesSpent += (ulong)reader.GetInt64(3); |
|
|
|
|
newItem.ids.Add(reader.GetInt32(0)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return items.Cast<CallTreeNode>().AsQueryable(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
string[] ids = parent.ids |
|
|
|
|
.Select(a => a.ToString(CultureInfo.InvariantCulture)) |
|
|
|
|
.ToArray(); |
|
|
|
|
|
|
|
|
|
return GetMergedFunctionData("parentid IN(" + string.Join(",", ids) + ")", parent.selectionStartIndex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internal IQueryable<CallTreeNode> GetCallers(SQLiteCallTreeNode item) |
|
|
|
@ -114,6 +90,7 @@ namespace ICSharpCode.Profiler.Controller.Data
@@ -114,6 +90,7 @@ namespace ICSharpCode.Profiler.Controller.Data
|
|
|
|
|
SQLiteCallTreeNode newItem = items.Find(node => node.nameId == childNameId); |
|
|
|
|
if (newItem == null) { |
|
|
|
|
newItem = new SQLiteCallTreeNode(childNameId, null, this); |
|
|
|
|
newItem.selectionStartIndex = item.selectionStartIndex; |
|
|
|
|
items.Add(newItem); |
|
|
|
|
|
|
|
|
|
// works because of ORDER BY id
|
|
|
|
@ -291,6 +268,8 @@ namespace ICSharpCode.Profiler.Controller.Data
@@ -291,6 +268,8 @@ namespace ICSharpCode.Profiler.Controller.Data
|
|
|
|
|
|
|
|
|
|
using (SQLiteDataReader reader = cmd.ExecuteReader()) { |
|
|
|
|
SQLiteCallTreeNode root = new SQLiteCallTreeNode(0, null, this); |
|
|
|
|
|
|
|
|
|
root.selectionStartIndex = startIndex; |
|
|
|
|
|
|
|
|
|
while (reader.Read()) { |
|
|
|
|
root.callCount += reader.GetInt32(2); |
|
|
|
@ -303,6 +282,7 @@ namespace ICSharpCode.Profiler.Controller.Data
@@ -303,6 +282,7 @@ namespace ICSharpCode.Profiler.Controller.Data
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#region Properties
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
public override void SetProperty(string name, string value) |
|
|
|
|
{ |
|
|
|
@ -349,6 +329,7 @@ namespace ICSharpCode.Profiler.Controller.Data
@@ -349,6 +329,7 @@ namespace ICSharpCode.Profiler.Controller.Data
|
|
|
|
|
|
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
int processorFrequency = -1; |
|
|
|
|
|
|
|
|
@ -375,35 +356,49 @@ namespace ICSharpCode.Profiler.Controller.Data
@@ -375,35 +356,49 @@ namespace ICSharpCode.Profiler.Controller.Data
|
|
|
|
|
if (endIndex < startIndex || endIndex >= this.DataSets.Count) |
|
|
|
|
throw new ArgumentOutOfRangeException("endIndex", endIndex, "Value must be between " + startIndex + " and " + (this.DataSets.Count - 1)); |
|
|
|
|
|
|
|
|
|
IList<CallTreeNode> functions = new List<CallTreeNode>(); |
|
|
|
|
var result = GetMergedFunctionData(string.Format("datasetid BETWEEN {0} AND {1}", startIndex, endIndex), startIndex); |
|
|
|
|
|
|
|
|
|
return result |
|
|
|
|
.Where(i => i.NameMapping.Id != 0 && !i.NameMapping.Name.StartsWith("Thread#", StringComparison.Ordinal)) |
|
|
|
|
.AsQueryable(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
IQueryable<CallTreeNode> GetMergedFunctionData(string condition, int startIndex) |
|
|
|
|
{ |
|
|
|
|
IList<CallTreeNode> result = new List<CallTreeNode>(); |
|
|
|
|
|
|
|
|
|
SQLiteCommand cmd; |
|
|
|
|
using (LockAndCreateCommand(out cmd)) { |
|
|
|
|
cmd.CommandText = @"SELECT GROUP_CONCAT(id), nameid, SUM(timespent), SUM(callcount)
|
|
|
|
|
FROM FunctionData |
|
|
|
|
WHERE datasetid BETWEEN @start AND @end |
|
|
|
|
GROUP BY nameid;";
|
|
|
|
|
cmd.Parameters.Add(new SQLiteParameter("@start", startIndex)); |
|
|
|
|
cmd.Parameters.Add(new SQLiteParameter("@end", endIndex)); |
|
|
|
|
cmd.CommandText = @"SELECT
|
|
|
|
|
GROUP_CONCAT(id), |
|
|
|
|
nameid, |
|
|
|
|
SUM(timespent), |
|
|
|
|
SUM(callcount), |
|
|
|
|
MAX(id != endid) AS hasChildren, |
|
|
|
|
SUM((datasetid = " + startIndex + @") AND isActiveAtStart) AS activeCallCount |
|
|
|
|
FROM FunctionData |
|
|
|
|
WHERE " + condition + @" |
|
|
|
|
GROUP BY nameid;";
|
|
|
|
|
|
|
|
|
|
using (SQLiteDataReader reader = cmd.ExecuteReader()) { |
|
|
|
|
|
|
|
|
|
while (reader.Read()) { |
|
|
|
|
SQLiteCallTreeNode node = new SQLiteCallTreeNode(reader.GetInt32(1), null, this); |
|
|
|
|
node.selectionStartIndex = startIndex; |
|
|
|
|
node.callCount = reader.GetInt32(3); |
|
|
|
|
node.cpuCyclesSpent = (ulong)reader.GetInt64(2); |
|
|
|
|
node.ids = reader.GetString(0).Split(',').Select(s => int.Parse(s)).ToList(); |
|
|
|
|
node.ids.Sort(); |
|
|
|
|
node.hasChildren = reader.GetBoolean(4); |
|
|
|
|
node.activeCallCount = reader.GetInt32(5); |
|
|
|
|
// Can not do filtering of root and thread nodes here,
|
|
|
|
|
// because retrieval of names needs access to DB
|
|
|
|
|
// which is forbidden now (we are inside the lock!)
|
|
|
|
|
functions.Add(node); |
|
|
|
|
result.Add(node); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Do filtering now via LINQ
|
|
|
|
|
return functions.SkipWhile(i => i.NameMapping.Id == 0 || i.NameMapping.Name.StartsWith("Thread#", StringComparison.Ordinal)).AsQueryable(); |
|
|
|
|
return result.AsQueryable(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
LockObject LockAndCreateCommand(out SQLiteCommand cmd) |
|
|
|
|