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 @@ +