From 5e9db63fbfdc614e49f274e1a07f8a7c4e142811 Mon Sep 17 00:00:00 2001 From: Aaron Stannard Date: Wed, 13 Apr 2016 17:49:06 -0700 Subject: [PATCH] added benchmark to illustrate potential memory leak with StandardOutWriter eliminated allocations inside StandardOutWriter --- .../Akka.FSharp/Properties/AssemblyInfo.fs | 9 +--- .../Akka.Tests.Performance.csproj | 5 +++ .../Util/StandardOutWriterMemoryBenchmark.cs | 43 +++++++++++++++++++ .../Akka.Tests.Performance/packages.config | 1 + src/core/Akka/Util/StandardOutWriter.cs | 26 +++++------ 5 files changed, 64 insertions(+), 20 deletions(-) create mode 100644 src/core/Akka.Tests.Performance/Util/StandardOutWriterMemoryBenchmark.cs diff --git a/src/core/Akka.FSharp/Properties/AssemblyInfo.fs b/src/core/Akka.FSharp/Properties/AssemblyInfo.fs index df352ed0ce0..88c69f73c78 100644 --- a/src/core/Akka.FSharp/Properties/AssemblyInfo.fs +++ b/src/core/Akka.FSharp/Properties/AssemblyInfo.fs @@ -1,11 +1,4 @@ -//----------------------------------------------------------------------- -// -// Copyright (C) 2009-2016 Typesafe Inc. -// Copyright (C) 2013-2016 Akka.NET project -// -//----------------------------------------------------------------------- - -namespace System +namespace System open System open System.Reflection open System.Runtime.InteropServices diff --git a/src/core/Akka.Tests.Performance/Akka.Tests.Performance.csproj b/src/core/Akka.Tests.Performance/Akka.Tests.Performance.csproj index bc0e7428d37..214f6e1ff68 100644 --- a/src/core/Akka.Tests.Performance/Akka.Tests.Performance.csproj +++ b/src/core/Akka.Tests.Performance/Akka.Tests.Performance.csproj @@ -34,6 +34,10 @@ ..\..\packages\NBench.0.2.1\lib\net45\NBench.dll True + + ..\..\packages\NBench.PerformanceCounters.0.2.1\lib\net45\NBench.PerformanceCounters.dll + True + @@ -53,6 +57,7 @@ + diff --git a/src/core/Akka.Tests.Performance/Util/StandardOutWriterMemoryBenchmark.cs b/src/core/Akka.Tests.Performance/Util/StandardOutWriterMemoryBenchmark.cs new file mode 100644 index 00000000000..9b4cd6bdd5a --- /dev/null +++ b/src/core/Akka.Tests.Performance/Util/StandardOutWriterMemoryBenchmark.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Akka.Util; +using NBench; +using NBench.PerformanceCounters; + +namespace Akka.Tests.Performance.Util +{ + /// + /// Testing to see if the use of delegates inside + /// results in allocations. + /// + public class StandardOutWriterMemoryBenchmark + { + private Counter _consoleWriteThroughputCounter; + private const string ConsoleWriteThroughputCounterName = "StandardOutWrites"; + private const string InputStr = "W"; // want to avoid string allocations for this spec + + [PerfSetup] + public void SetUp(BenchmarkContext context) + { + _consoleWriteThroughputCounter = context.GetCounter(ConsoleWriteThroughputCounterName); + } + + [PerfBenchmark(Description = "Testing to see if the design of the StandardOutWriter produces allocations", + RunMode = RunMode.Throughput, + NumberOfIterations = 13, TestMode = TestMode.Measurement, RunTimeMilliseconds = 1000)] + [CounterMeasurement(ConsoleWriteThroughputCounterName)] + [MemoryAssertion(MemoryMetric.TotalBytesAllocated, MustBe.LessThan, ByteConstants.SixtyFourKb)] + [GcMeasurement(GcMetric.TotalCollections, GcGeneration.AllGc)] + [PerformanceCounterMeasurement(".NET CLR Memory", "# of Pinned Objects", InstanceName = NBenchPerformanceCounterConstants.CurrentProcessName, UnitName = "objects")] + [PerformanceCounterMeasurement(".NET CLR Memory", "# Bytes in all Heaps", InstanceName = NBenchPerformanceCounterConstants.CurrentProcessName, UnitName = "bytes")] + [PerformanceCounterMeasurement(".NET CLR Memory", "# GC Handles", InstanceName = NBenchPerformanceCounterConstants.CurrentProcessName, UnitName = "handles")] + public void StressTestStandardOutWriter(BenchmarkContext context) + { + StandardOutWriter.WriteLine(InputStr, ConsoleColor.Black, ConsoleColor.DarkGreen); + _consoleWriteThroughputCounter.Increment(); + } + } +} diff --git a/src/core/Akka.Tests.Performance/packages.config b/src/core/Akka.Tests.Performance/packages.config index bc9c73a6da5..9a3df0d1914 100644 --- a/src/core/Akka.Tests.Performance/packages.config +++ b/src/core/Akka.Tests.Performance/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/src/core/Akka/Util/StandardOutWriter.cs b/src/core/Akka/Util/StandardOutWriter.cs index 27cefcb3764..476df13c31a 100644 --- a/src/core/Akka/Util/StandardOutWriter.cs +++ b/src/core/Akka/Util/StandardOutWriter.cs @@ -24,9 +24,10 @@ public static class StandardOutWriter /// The value to write /// Optional: The foreground color /// Optional: The background color - public static void Write(string message, ConsoleColor? foregroundColor = null, ConsoleColor? backgroundColor = null) + public static void Write(string message, ConsoleColor? foregroundColor = null, + ConsoleColor? backgroundColor = null) { - WriteToConsole(() => Console.Write(message), foregroundColor, backgroundColor); + WriteToConsole(message, foregroundColor, backgroundColor); } /// @@ -37,33 +38,35 @@ public static void Write(string message, ConsoleColor? foregroundColor = null, C /// Optional: The foreground color /// Optional: The background color - public static void WriteLine(string message, ConsoleColor? foregroundColor = null, ConsoleColor? backgroundColor = null) + public static void WriteLine(string message, ConsoleColor? foregroundColor = null, + ConsoleColor? backgroundColor = null) { - WriteToConsole(() => Console.WriteLine(message), foregroundColor, backgroundColor); + WriteToConsole(message, foregroundColor, backgroundColor); } - private static void WriteToConsole(Action write, ConsoleColor? foregroundColor = null, ConsoleColor? backgroundColor = null) + private static void WriteToConsole(string message, ConsoleColor? foregroundColor = null, + ConsoleColor? backgroundColor = null) { - lock(_lock) + lock (_lock) { ConsoleColor? fg = null; - if(foregroundColor.HasValue) + if (foregroundColor.HasValue) { fg = Console.ForegroundColor; Console.ForegroundColor = foregroundColor.Value; } ConsoleColor? bg = null; - if(backgroundColor.HasValue) + if (backgroundColor.HasValue) { bg = Console.BackgroundColor; Console.BackgroundColor = backgroundColor.Value; } - write(); - if(fg.HasValue) + Console.WriteLine(message); + if (fg.HasValue) { Console.ForegroundColor = fg.Value; } - if(bg.HasValue) + if (bg.HasValue) { Console.BackgroundColor = bg.Value; } @@ -71,4 +74,3 @@ private static void WriteToConsole(Action write, ConsoleColor? foregroundColor = } } } -