diff --git a/src/AddIns/Misc/Profiler/Controller/Data/CallTreeNode.cs b/src/AddIns/Misc/Profiler/Controller/Data/CallTreeNode.cs
index 1af3fce29f..faed9aa100 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/CallTreeNode.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/CallTreeNode.cs
@@ -109,9 +109,9 @@ namespace ICSharpCode.Profiler.Controller.Data
}
///
- /// Determines whether this node is a thread node or not.
+ /// Determines whether this node is a thread node.
///
- public bool IsThread {
+ public virtual bool IsThread {
get { return this.Name.StartsWith("Thread#", StringComparison.Ordinal); }
}
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/Linq/KnownMembers.cs b/src/AddIns/Misc/Profiler/Controller/Data/Linq/KnownMembers.cs
index 1a951606dd..963d0465cf 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/Linq/KnownMembers.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/Linq/KnownMembers.cs
@@ -16,6 +16,7 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
static class KnownMembers
{
public static readonly PropertyInfo CallTreeNode_IsUserCode = PropertyOf((CallTreeNode c) => c.IsUserCode);
+ public static readonly PropertyInfo CallTreeNode_IsThread = PropertyOf((CallTreeNode c) => c.IsThread);
public static readonly PropertyInfo CallTreeNode_CpuCyclesSpent = PropertyOf((CallTreeNode c) => c.CpuCyclesSpent);
public static readonly PropertyInfo CallTreeNode_CallCount = PropertyOf((CallTreeNode c) => c.CallCount);
public static readonly PropertyInfo CallTreeNode_NameMapping = PropertyOf((CallTreeNode c) => c.NameMapping);
@@ -29,8 +30,12 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
public static readonly MethodInfo QueryableOfCallTreeNode_Take = MethodOf((IQueryable q) => q.Take(1));
public static readonly MethodInfo Queryable_OrderBy = MethodOf((IQueryable q) => q.OrderBy(x => x)).GetGenericMethodDefinition();
public static readonly MethodInfo QueryableOfCallTreeNode_OrderByDesc = MethodOf((IOrderedQueryable q) => q.OrderByDescending(x => default(int)));
- public static readonly MethodInfo Merge = MethodOf((IQueryable q) => q.Merge());
public static readonly MethodInfo String_StartsWith = MethodOf((string s) => s.StartsWith(s, default(StringComparison)));
+
+ public static readonly MethodInfo Queryable_Merge = MethodOf((IQueryable q) => q.Merge());
+ public static readonly MethodInfo Queryable_MergeByName = MethodOf((IQueryable q) => q.MergeByName());
+ public static readonly MethodInfo Queryable_WithQueryLog = MethodOf((IQueryable q) => q.WithQueryLog(null));
+
public static readonly MethodInfo Like = MethodOf(() => LikeImpl("", ""));
public static readonly MethodInfo Glob = MethodOf(() => GlobImpl("", ""));
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/Linq/QueryAst.cs b/src/AddIns/Misc/Profiler/Controller/Data/Linq/QueryAst.cs
index d250e08a84..7025033655 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/Linq/QueryAst.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/Linq/QueryAst.cs
@@ -105,12 +105,19 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
return expression + " AS " + newName;
}
- public virtual IQueryable Execute(SQLiteQueryProvider provider)
+ public IQueryable Execute(SQLiteQueryProvider provider, QueryExecutionOptions options)
{
StringBuilder b = new StringBuilder();
BuildSql(b, new SqlQueryContext(provider));
- Console.WriteLine(b.ToString());
- return provider.RunSQLNodeList(b.ToString()).AsQueryable();
+ if (options.HasLoggers)
+ options.WriteLogLine(b.ToString());
+ Stopwatch w = Stopwatch.StartNew();
+ IList result = provider.RunSQLNodeList(b.ToString());
+ w.Stop();
+ if (options.HasLoggers) {
+ options.WriteLogLine("Query returned " + result.Count + " rows in " + w.Elapsed);
+ }
+ return result.AsQueryable();
}
}
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/Linq/SQLiteQueryProvider.cs b/src/AddIns/Misc/Profiler/Controller/Data/Linq/SQLiteQueryProvider.cs
index 27247a7279..cb35ee7c69 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/Linq/SQLiteQueryProvider.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/Linq/SQLiteQueryProvider.cs
@@ -7,6 +7,8 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
@@ -82,8 +84,9 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
Translation rules for expression importer:
Any valid expressions (as defined in 'valid expressions in QueryAst nodes') are copied over directly.
- Moreover, these expressions are be converted into valid expressions:
+ Moreover, these expressions are converted into valid expressions:
c.IsUserCode -> c.NameMapping.ID > 0
+ c.IsThread -> Glob(c.NameMapping.Name, "Thread#*")
s.StartsWith(constantString, StringComparison.Ordinal) -> Glob(s, constantString + "*");
s.StartsWith(constantString, StringComparison.OrdinalIgnoreCase) -> Like(s, constantString + "%");
@@ -159,31 +162,43 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
return expression.ToString();
}
- public override object Execute(Expression expression)
+ public override object Execute(Expression inputExpression)
{
- Console.WriteLine("Input expression: " + expression);
+ Stopwatch watch = Stopwatch.StartNew();
+ Expression partiallyEvaluatedExpression = PartialEvaluator.Eval(inputExpression, CanBeEvaluatedStatically);
- expression = PartialEvaluator.Eval(expression, CanBeEvaluatedStatically);
- Console.WriteLine("Partially evaluated expression: " + expression);
-
- expression = new ConvertToQueryAstVisitor().Visit(expression);
- Console.WriteLine("Converted to Query AST: " + expression);
+ QueryExecutionOptions options = new QueryExecutionOptions();
+ Expression expression = new ConvertToQueryAstVisitor(options).Visit(partiallyEvaluatedExpression);
+ // options have been initialized by ConvertToQueryAstVisitor, start logging:
+ if (options.HasLoggers) {
+ options.WriteLogLine("Input expression: " + inputExpression);
+ options.WriteLogLine("Partially evaluated expression: " + partiallyEvaluatedExpression);
+ options.WriteLogLine("Converted to Query AST: " + expression);
+ }
expression = new OptimizeQueryExpressionVisitor().Visit(expression);
- Console.WriteLine("Optimized Query AST: " + expression);
+ if (options.HasLoggers) {
+ options.WriteLogLine("Optimized Query AST: " + expression);
+ options.WriteLogLine("Query preparation time: " + watch.Elapsed);
+ }
+ object result;
// If the whole query was converted, execute it:
QueryNode query = expression as QueryNode;
- if (query != null)
- return query.Execute(this);
-
- // Query not converted completely: we have to use a LINQ-To-Objects / LINQ-To-Profiler mix
- expression = new ExecuteAllQueriesVisitor(this).Visit(expression);
- if (expression.Type.IsValueType) {
- expression = Expression.Convert(expression, typeof(object));
+ if (query != null) {
+ result = query.Execute(this, options);
+ } else {
+ // Query not converted completely: we have to use a LINQ-To-Objects / LINQ-To-Profiler mix
+ expression = new ExecuteAllQueriesVisitor(this, options).Visit(expression);
+ if (expression.Type.IsValueType) {
+ expression = Expression.Convert(expression, typeof(object));
+ }
+ var lambdaExpression = Expression.Lambda>(expression);
+ result = lambdaExpression.Compile()();
}
- var lambdaExpression = Expression.Lambda>(expression);
- return lambdaExpression.Compile()();
+ watch.Stop();
+ options.WriteLogLine("Total query execution time: " + watch.Elapsed);
+ return result;
}
static bool CanBeEvaluatedStatically(Expression expression)
@@ -194,6 +209,13 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
#region Convert Expression Tree To Query AST
sealed class ConvertToQueryAstVisitor : System.Linq.Expressions.ExpressionVisitor
{
+ readonly QueryExecutionOptions options;
+
+ public ConvertToQueryAstVisitor(QueryExecutionOptions options)
+ {
+ this.options = options;
+ }
+
protected override Expression VisitExtension(Expression node)
{
// We found a query that's already converted, let's keep it as it is.
@@ -233,6 +255,9 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
}
}
}
+ } else if (node.Method == KnownMembers.Queryable_WithQueryLog && node.Arguments[1].NodeType == ExpressionType.Constant) {
+ options.AddLogger((TextWriter)(((ConstantExpression)node.Arguments[1]).Value));
+ return Visit(node.Arguments[0]);
} else if (node.Method == KnownMembers.QueryableOfCallTreeNode_Take && node.Arguments[1].NodeType == ExpressionType.Constant) {
ConstantExpression ce = (ConstantExpression)node.Arguments[1];
if (ce.Type == typeof(int)) {
@@ -269,10 +294,12 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
return base.VisitMethodCall(node);
}
}
+ #endregion
+ #region SafeExpressionImporter
sealed class SafeExpressionImporter
{
- ParameterExpression callTreeNodeParameter;
+ readonly ParameterExpression callTreeNodeParameter;
public SafeExpressionImporter(ParameterExpression callTreeNodeParameter)
{
@@ -335,6 +362,10 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
Expression.Property(callTreeNodeParameter, KnownMembers.CallTreeNode_NameMapping),
KnownMembers.NameMapping_ID),
Expression.Constant(0));
+ } else if (me.Member == KnownMembers.CallTreeNode_IsThread) {
+ return Expression.Call(KnownMembers.Glob,
+ Expression.Property(Expression.Property(callTreeNodeParameter, KnownMembers.CallTreeNode_NameMapping), KnownMembers.NameMapping_Name),
+ Expression.Constant("Thread#*"));
}
if (me.Member == KnownMembers.CallTreeNode_CallCount)
@@ -437,21 +468,44 @@ namespace ICSharpCode.Profiler.Controller.Data.Linq
sealed class ExecuteAllQueriesVisitor : System.Linq.Expressions.ExpressionVisitor
{
readonly SQLiteQueryProvider sqliteProvider;
+ readonly QueryExecutionOptions options;
- public ExecuteAllQueriesVisitor(SQLiteQueryProvider sqliteProvider)
+ public ExecuteAllQueriesVisitor(SQLiteQueryProvider sqliteProvider, QueryExecutionOptions options)
{
this.sqliteProvider = sqliteProvider;
+ this.options = options;
}
protected override Expression VisitExtension(Expression node)
{
QueryNode query = node as QueryNode;
if (query != null)
- return Expression.Constant(query.Execute(sqliteProvider));
+ return Expression.Constant(query.Execute(sqliteProvider, options));
else
return base.VisitExtension(node);
}
}
#endregion
}
+
+ sealed class QueryExecutionOptions
+ {
+ List loggers = new List();
+
+ public void AddLogger(TextWriter w)
+ {
+ if (w != null)
+ loggers.Add(w);
+ }
+
+ public bool HasLoggers {
+ get { return loggers.Count > 0; }
+ }
+
+ public void WriteLogLine(string text)
+ {
+ foreach (TextWriter w in loggers)
+ w.WriteLine(text);
+ }
+ }
}
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataProvider.cs b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataProvider.cs
index b18606abc6..04f5e774a8 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataProvider.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataProvider.cs
@@ -65,7 +65,7 @@ namespace ICSharpCode.Profiler.Controller.Data
///
public virtual IQueryable GetFunctions(int startIndex, int endIndex)
{
- return GetRoot(startIndex, endIndex).Descendants.GroupBy(n => n.NameMapping).Select(g => g.Merge());
+ return GetRoot(startIndex, endIndex).Descendants.Where(c => !c.IsThread).MergeByName();
}
}
}
diff --git a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
index 138cd76efe..60e49df261 100644
--- a/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Data/ProfilingDataSQLiteProvider.cs
@@ -274,7 +274,7 @@ namespace ICSharpCode.Profiler.Controller.Data
var query = queryProvider.CreateQuery(new MergeByName(new Filter(AllCalls.Instance, DataSetFilter(startIndex, endIndex))));
return from c in query
- where c.NameMapping.Id != 0 && !c.NameMapping.Name.StartsWith("Thread#", StringComparison.Ordinal)
+ where c.NameMapping.Id != 0 && !c.IsThread
select c;
}
diff --git a/src/AddIns/Misc/Profiler/Controller/ExtensionMethods.cs b/src/AddIns/Misc/Profiler/Controller/ExtensionMethods.cs
index f9917d015f..7b01225ea1 100644
--- a/src/AddIns/Misc/Profiler/Controller/ExtensionMethods.cs
+++ b/src/AddIns/Misc/Profiler/Controller/ExtensionMethods.cs
@@ -2,6 +2,7 @@
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
@@ -32,7 +33,19 @@ namespace ICSharpCode.Profiler.Controller
return builder.ToString();
}
-
+
+ ///
+ /// Returns a CallTreeNode with all merged items.
+ ///
+ public static CallTreeNode Merge(this IQueryable items)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
+
+ return items.Provider.Execute(
+ Expression.Call(Data.Linq.KnownMembers.Queryable_Merge, items.Expression));
+ }
+
///
/// Returns a CallTreeNode with all merged items.
///
@@ -41,16 +54,60 @@ namespace ICSharpCode.Profiler.Controller
if (items == null)
throw new ArgumentNullException("items");
- Debug.Assert(MethodBase.GetCurrentMethod() == Data.Linq.KnownMembers.Merge);
+ var itemList = items.ToList();
+ return itemList.First().Merge(items);
+ }
+
+ ///
+ /// Merges CallTreeNodes with identical name mappings.
+ ///
+ public static IQueryable MergeByName(this IQueryable items)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
- IQueryable query = items as IQueryable;
- if (query != null) {
- return query.Provider.Execute(
- Expression.Call(Data.Linq.KnownMembers.Merge, query.Expression));
- } else {
- var itemList = items.ToList();
- return itemList.First().Merge(items);
- }
+ return items.Provider.CreateQuery(
+ Expression.Call(Data.Linq.KnownMembers.Queryable_MergeByName, items.Expression));
+ }
+
+ ///
+ /// Merges CallTreeNodes with identical name mappings.
+ ///
+ public static IEnumerable MergeByName(this IEnumerable items)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
+
+ return items.GroupBy(c => c.NameMapping).Select(g => g.Merge());
+ }
+
+ ///
+ /// Tells the query execution to add logging to the query.
+ ///
+ public static IQueryable WithQueryLog(this IQueryable items, TextWriter logOutput)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
+ if (logOutput == null)
+ throw new ArgumentNullException("logOutput");
+
+ return items.Provider.CreateQuery(
+ Expression.Call(Data.Linq.KnownMembers.Queryable_WithQueryLog, items.Expression, Expression.Constant(logOutput)));
+ }
+
+ ///
+ /// Tells the query execution to add logging to the query.
+ ///
+ public static IEnumerable WithQueryLog(this IEnumerable items, TextWriter logOutput)
+ {
+ if (items == null)
+ throw new ArgumentNullException("items");
+ if (logOutput == null)
+ throw new ArgumentNullException("logOutput");
+
+ logOutput.WriteLine("The query did not use LINQ-to-Profiler.");
+
+ return items;
}
///
diff --git a/src/AddIns/Misc/Profiler/Controller/Interprocess/UnmanagedCircularBuffer.cs b/src/AddIns/Misc/Profiler/Controller/Interprocess/UnmanagedCircularBuffer.cs
index 152ab4f188..473662d63e 100644
--- a/src/AddIns/Misc/Profiler/Controller/Interprocess/UnmanagedCircularBuffer.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Interprocess/UnmanagedCircularBuffer.cs
@@ -165,14 +165,20 @@ namespace ICSharpCode.Profiler.Interprocess
///
/// Closes the circular buffer.
///
- public void Close()
+ ///
+ /// Specifies whether the close method should wait for the active reader thread to exit.
+ /// If you pass true, but there is no reader thread; the Close method will deadlock.
+ /// If you pass false, but there is a reader thread; the reader thread will crash.
+ ///
+ public void Close(bool waitForReaderThreadExit)
{
lock (closeLock) {
if (isClosed)
return;
isClosed = true;
nonEmptyEvent.Set();
- Monitor.Wait(closeLock);
+ if (waitForReaderThreadExit)
+ Monitor.Wait(closeLock);
}
nonEmptyEvent.Close();
nonFullEvent.Close();
@@ -181,7 +187,7 @@ namespace ICSharpCode.Profiler.Interprocess
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
void IDisposable.Dispose()
{
- Close();
+ Close(false);
}
#endregion
@@ -374,7 +380,7 @@ namespace ICSharpCode.Profiler.Interprocess
int writeCount = Math.Min(count, writeEndOffset - endOffset);
Debug.Assert(writeCount > 0);
- Debug.WriteLine("UnmanagedCircularBuffer: write amount " + writeCount);
+ //Debug.WriteLine("UnmanagedCircularBuffer: write amount " + writeCount);
Marshal.Copy(buffer, offset, new IntPtr(circularBuffer.data + endOffset), writeCount);
endOffset += writeCount; // advance endOffset
diff --git a/src/AddIns/Misc/Profiler/Controller/Profiler.cs b/src/AddIns/Misc/Profiler/Controller/Profiler.cs
index b324242a25..f3ec1582ce 100644
--- a/src/AddIns/Misc/Profiler/Controller/Profiler.cs
+++ b/src/AddIns/Misc/Profiler/Controller/Profiler.cs
@@ -591,7 +591,7 @@ namespace ICSharpCode.Profiler.Controller
this.stopDC = true;
Debug.WriteLine("Closing native to managed buffer");
- nativeToManagedBuffer.Close();
+ nativeToManagedBuffer.Close(true);
Debug.WriteLine("Joining logger thread...");
this.logger.Join();
@@ -786,7 +786,7 @@ namespace ICSharpCode.Profiler.Controller
if (!isDisposed) {
isDisposed = true;
stopDC = true;
- nativeToManagedBuffer.Close();
+ nativeToManagedBuffer.Close(true);
try {
this.profilee.Kill();
} catch (InvalidOperationException) {
diff --git a/src/AddIns/Misc/Profiler/Frontend/Controls/QueryView.xaml.cs b/src/AddIns/Misc/Profiler/Frontend/Controls/QueryView.xaml.cs
index 6c0f0a6bf1..3967c216e0 100644
--- a/src/AddIns/Misc/Profiler/Frontend/Controls/QueryView.xaml.cs
+++ b/src/AddIns/Misc/Profiler/Frontend/Controls/QueryView.xaml.cs
@@ -189,29 +189,32 @@ namespace ICSharpCode.Profiler.Controls
this.Translation = new ControlsTranslation();
this.visibleColumnsSelection.ItemsSource = this.gridView.Columns.Select(col => new GridViewColumnModel(col));
- this.treeView.SizeChanged += delegate(object sender, SizeChangedEventArgs e) {
- if (e.NewSize.Width > 0 && e.PreviousSize.Width > 0) {
- double adjustedNameColumnWidth = nameColumn.Width + e.NewSize.Width - e.PreviousSize.Width;
- double matchingNameColumnWidth = e.NewSize.Width - this.callCountColumn.Width
- - this.percentColumn.Width - this.timeSpentColumn.Width
- - this.timeSpentSelfColumn.Width - this.timeSpentPerCallColumn.Width
- - this.timeSpentSelfPerCallColumn.Width - 25;
-
- // always keep name column at least 75 pixels wide
- if (matchingNameColumnWidth < 75)
- matchingNameColumnWidth = 75;
-
- if (e.NewSize.Width >= e.PreviousSize.Width) {
- // treeView got wider: also make name column wider if there's space free
- if (adjustedNameColumnWidth <= matchingNameColumnWidth)
- nameColumn.Width = adjustedNameColumnWidth;
- } else {
- // treeView got smaller: make column smaller unless there's space free
- if (adjustedNameColumnWidth >= matchingNameColumnWidth)
- nameColumn.Width = adjustedNameColumnWidth;
- }
+ this.treeView.SizeChanged += QueryView_SizeChanged;
+ }
+
+ void QueryView_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ if (e.NewSize.Width > 0 && e.PreviousSize.Width > 0) {
+ double adjustedNameColumnWidth = nameColumn.Width + e.NewSize.Width - e.PreviousSize.Width;
+ double matchingNameColumnWidth = e.NewSize.Width - this.callCountColumn.Width
+ - this.percentColumn.Width - this.timeSpentColumn.Width
+ - this.timeSpentSelfColumn.Width - this.timeSpentPerCallColumn.Width
+ - this.timeSpentSelfPerCallColumn.Width - 25;
+
+ // always keep name column at least 75 pixels wide
+ if (matchingNameColumnWidth < 75)
+ matchingNameColumnWidth = 75;
+
+ if (e.NewSize.Width >= e.PreviousSize.Width) {
+ // treeView got wider: also make name column wider if there's space free
+ if (adjustedNameColumnWidth <= matchingNameColumnWidth)
+ nameColumn.Width = adjustedNameColumnWidth;
+ } else {
+ // treeView got smaller: make column smaller unless there's space free
+ if (adjustedNameColumnWidth >= matchingNameColumnWidth)
+ nameColumn.Width = adjustedNameColumnWidth;
}
- };
+ }
}
public void SetRange(int start, int end)
@@ -290,6 +293,9 @@ namespace ICSharpCode.Profiler.Controls
try {
if (compiler.Compile()) {
var data = compiler.ExecuteQuery(provider, rangeStart, rangeEnd);
+ #if DEBUG
+ data = data.WithQueryLog(Console.Out);
+ #endif
var nodes = data.Select(i => new CallTreeNodeViewModel(i, null)).ToList();
return new HierarchyList(nodes);
}
diff --git a/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/Data/LinqTests.cs b/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/Data/LinqTests.cs
index 51a8cce9bf..df43302e50 100644
--- a/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/Data/LinqTests.cs
+++ b/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/Data/LinqTests.cs
@@ -10,6 +10,7 @@ using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;
+using ICSharpCode.Profiler.Controller;
using ICSharpCode.Profiler.Controller.Data;
using ICSharpCode.Profiler.Controller.Data.Linq;
using NUnit.Framework;
@@ -129,7 +130,7 @@ namespace Profiler.Tests.Controller.Data
[Test]
public void TestFunctions()
{
- CallTreeNode[] functions = provider.GetFunctions(1, 2).OrderBy(f => f.Name).ToArray();
+ CallTreeNode[] functions = provider.GetFunctions(1, 2).OrderBy(f => f.Name).WithQueryLog(Console.Out).ToArray();
Assert.AreEqual(2, functions.Length);
Assert.AreEqual("m1", functions[0].Name);
diff --git a/src/AddIns/Misc/Profiler/Controller/Interprocess/UnmanagedCircularBufferTest.cs b/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/UnmanagedCircularBufferTest.cs
similarity index 97%
rename from src/AddIns/Misc/Profiler/Controller/Interprocess/UnmanagedCircularBufferTest.cs
rename to src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/UnmanagedCircularBufferTest.cs
index caceaa09bf..ddcc84fd97 100644
--- a/src/AddIns/Misc/Profiler/Controller/Interprocess/UnmanagedCircularBufferTest.cs
+++ b/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Controller/UnmanagedCircularBufferTest.cs
@@ -10,6 +10,7 @@ using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
+using ICSharpCode.Profiler.Interprocess;
using NUnit.Framework;
namespace Profiler.Interprocess
@@ -83,7 +84,7 @@ namespace Profiler.Interprocess
using (Stream ws = ncb.CreateWritingStream()) {
ws.WriteByte(0x42);
}
- using (UnmanagedCircularBuffer ncb2 = UnmanagedCircularBuffer.Open(memoryStart, memoryLength)) {
+ using (UnmanagedCircularBuffer ncb2 = UnmanagedCircularBuffer.Open(memoryStart)) {
using (Stream rs = ncb2.CreateReadingStream()) {
Assert.AreEqual(0x42, rs.ReadByte());
}
@@ -104,7 +105,7 @@ namespace Profiler.Interprocess
using (MemoryMappedFile mmf2 = MemoryMappedFile.Open("Local\\TestMemory")) {
using (UnmanagedMemory view2 = mmf1.MapView(0, 1024)) {
Assert.AreNotEqual(view1.Start, view2.Start);
- using (UnmanagedCircularBuffer ncb2 = UnmanagedCircularBuffer.Open(view2.Start, (int)view2.Length)) {
+ using (UnmanagedCircularBuffer ncb2 = UnmanagedCircularBuffer.Open(view2.Start)) {
using (Stream rs = ncb2.CreateReadingStream()) {
Assert.AreEqual(0x42, rs.ReadByte());
}
diff --git a/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Profiler.Tests.csproj b/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Profiler.Tests.csproj
index 76d485d70b..45c683306d 100644
--- a/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Profiler.Tests.csproj
+++ b/src/AddIns/Misc/Profiler/Tests/Profiler.Tests/Profiler.Tests.csproj
@@ -92,6 +92,7 @@
+