static void Main() { // tell BenchmarkDotNet not to force GC.Collect after benchmark iteration // (single iteration contains of multiple (usually millions) of invocations) // it can influence the allocation-heavy Task<T> benchmarks var gcMode = new GcMode { Force = false }; var customConfig = ManualConfig .Create(DefaultConfig.Instance) // copies all exporters, loggers and basic stuff .With(JitOptimizationsValidator.FailOnError) // Fail if not release mode .With(MemoryDiagnoser.Default) // use memory diagnoser .With(StatisticColumn.OperationsPerSecond) // add ops/s .With(Job.Default.With(gcMode)); #if NET462 // enable the Inlining Diagnoser to find out what does not get inlined // uncomment it first, it produces a lot of output //customConfig = customConfig.With(new BenchmarkDotNet.Diagnostics.Windows.InliningDiagnoser(logFailuresOnly: true, filterByNamespace: true)); #endif var summary = BenchmarkRunner.Run <PerformanceTests>(customConfig); Console.WriteLine(summary); }
private static void GenerateGCSettings(XmlDocument xmlDocument, XmlNode runtimeElement, GcMode gcMode, IResolver resolver) { if (!gcMode.HasChanges) return; CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcConcurrent", "enabled", gcMode.ResolveValue(GcMode.ConcurrentCharacteristic, resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcServer", "enabled", gcMode.ResolveValue(GcMode.ServerCharacteristic, resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "GCCpuGroup", "enabled", gcMode.ResolveValue(GcMode.CpuGroupsCharacteristic, resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcAllowVeryLargeObjects", "enabled", gcMode.ResolveValue(GcMode.AllowVeryLargeObjectsCharacteristic, resolver).ToLowerCase()); }
private static string SetGcMode(string content, GcMode gcMode, IResolver resolver) { if (gcMode.ToSet().GetValues().All(c => c.IsDefault)) { return(content.Replace("$GC$", null)); } return(content.Replace( "$GC$", $"\"runtimeOptions\": {{ \"configProperties\": {{ \"System.GC.Concurrent\": {gcMode.Concurrent.Resolve(resolver).ToLowerCase()}, \"System.GC.Server\": {gcMode.Server.Resolve(resolver).ToLowerCase()} }} }}, ")); }
private string SetGcMode(string content, GcMode gcMode) { if (gcMode == new GcMode()) { return(content.Replace("$GC$", null)); } return(content.Replace( "$GC$", $"\"runtimeOptions\": {{ \"configProperties\": {{ \"System.GC.Concurrent\": {gcMode.Concurrent.ToLowerCase()}, \"System.GC.Server\": {gcMode.Server.ToLowerCase()} }} }}, ")); }
private static void GcCollect(GcMode gcMode) { if (!gcMode.Force) { return; } GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); }
private static string SetGcMode(string content, GcMode gcMode, IResolver resolver) { if (!gcMode.HasChanges) { return(content.Replace("$GC$", null)); } return(content.Replace( "$GC$", $"\"runtimeOptions\": {{ \"configProperties\": {{ " + $"\"System.GC.Concurrent\": {gcMode.ResolveValue(GcMode.ConcurrentCharacteristic, resolver).ToLowerCase()}, " + $"\"System.GC.Server\": {gcMode.ResolveValue(GcMode.ServerCharacteristic, resolver).ToLowerCase()} }} }}, ")); }
protected virtual string GetRuntimeSettings(GcMode gcMode, IResolver resolver) { var builder = new StringBuilder(80) .AppendLine("<PropertyGroup>") .AppendLine($"<ServerGarbageCollection>{gcMode.ResolveValue(GcMode.ServerCharacteristic, resolver).ToLowerCase()}</ServerGarbageCollection>") .AppendLine($"<ConcurrentGarbageCollection>{gcMode.ResolveValue(GcMode.ConcurrentCharacteristic, resolver).ToLowerCase()}</ConcurrentGarbageCollection>"); if (gcMode.HasValue(GcMode.RetainVmCharacteristic)) { builder.AppendLine($"<RetainVMGarbageCollection>{gcMode.ResolveValue(GcMode.RetainVmCharacteristic, resolver).ToLowerCase()}</RetainVMGarbageCollection>"); } return(builder.AppendLine("</PropertyGroup>").ToString()); }
private string GetRuntimeSettings(GcMode gcMode, IResolver resolver) { if (!gcMode.HasChanges) { return(string.Empty); } return(new StringBuilder(80) .AppendLine("<PropertyGroup>") .AppendLine($"<ServerGarbageCollection>{gcMode.ResolveValue(GcMode.ServerCharacteristic, resolver).ToLowerCase()}</ServerGarbageCollection>") .AppendLine($"<ConcurrentGarbageCollection>{gcMode.ResolveValue(GcMode.ConcurrentCharacteristic, resolver).ToLowerCase()}</ConcurrentGarbageCollection>") .AppendLine($"<RetainVMGarbageCollection>{gcMode.ResolveValue(GcMode.RetainVmCharacteristic, resolver).ToLowerCase()}</RetainVMGarbageCollection>") .AppendLine("</PropertyGroup>") .ToString()); }
public AllocationsConfig() { var gcSettings = new GcMode() { Force = true, // tell BenchmarkDotNet to force GC collections after every iteration Server = true // we want to have the biggest Largest No GC Region possible }; Jit jit = Jit.RyuJit; // we want to run for x64 only, again to have the biggest Largest No GC Region possible Add(Job.Default .With(CsProjNet46Toolchain.Instance) .With(gcSettings.UnfreezeCopy()) .With(jit) .WithId(".NET 4.6")); // .NET Core 1.1 does not support GC.TryStartNoGCRegion method so we don't try it // .NET Core 2.0 fails when trying to call GC.TryStartNoGCRegion }
public AllocationsConfig() { var gcSettings = new GcMode { Force = false // tell BenchmarkDotNet not to force GC collections after every iteration }; const int invocationCount = 1 << 20; // let's run it very fast, we are here only for the GC stats Add(Job .RyuJitX64 // 64 bit .WithInvocationCount(invocationCount) .With(gcSettings.UnfreezeCopy())); Add(Job .LegacyJitX86 // 32 bit .WithInvocationCount(invocationCount) .With(gcSettings.UnfreezeCopy())); Add(MemoryDiagnoser.Default); }
private static void GenerateGCSettings(XmlDocument xmlDocument, XmlNode runtimeElement, GcMode gcMode, IResolver resolver) { if (!gcMode.HasChanges) { return; } CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcConcurrent", "enabled", gcMode.ResolveValue(GcMode.ConcurrentCharacteristic, resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcServer", "enabled", gcMode.ResolveValue(GcMode.ServerCharacteristic, resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "GCCpuGroup", "enabled", gcMode.ResolveValue(GcMode.CpuGroupsCharacteristic, resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcAllowVeryLargeObjects", "enabled", gcMode.ResolveValue(GcMode.AllowVeryLargeObjectsCharacteristic, resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "GCNoAffinitize", "enabled", gcMode.ResolveValue(GcMode.NoAffinitizeCharacteristic, resolver).ToLowerCase()); if (gcMode.HasValue(GcMode.HeapAffinitizeMaskCharacteristic)) { CreateNodeWithAttribute(xmlDocument, runtimeElement, "GCHeapAffinitizeMask", "enabled", gcMode.ResolveValue(GcMode.HeapAffinitizeMaskCharacteristic, resolver).ToString()); } if (gcMode.HasValue(GcMode.HeapCountCharacteristic)) { CreateNodeWithAttribute(xmlDocument, runtimeElement, "GCHeapCount", "enabled", gcMode.ResolveValue(GcMode.HeapCountCharacteristic, resolver).ToString()); } }
public static Job With(this Job job, GcMode gc) => job.WithCore(j => EnvMode.GcCharacteristic[j] = gc);
private IConfig CreateConfig(GcMode gc) => ManualConfig.CreateEmpty().With(new Job(Job.Dry, gc));
private static void GenerateGCSettings(XmlDocument xmlDocument, XmlNode runtimeElement, GcMode gcMode, IResolver resolver) { if (gcMode.ToSet().GetValues().All(c => c.IsDefault)) { return; } CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcConcurrent", "enabled", gcMode.Concurrent.Resolve(resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcServer", "enabled", gcMode.Server.Resolve(resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "GCCpuGroup", "enabled", gcMode.CpuGroups.Resolve(resolver).ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcAllowVeryLargeObjects", "enabled", gcMode.AllowVeryLargeObjects.Resolve(resolver).ToLowerCase()); }
private Measurement MultiInvoke <T>(IterationMode mode, int index, Action setupAction, Func <T> targetAction, Action cleanupAction, long invocationCount, long operationsPerInvoke, GcMode gcMode, T returnHolder = default(T)) { var totalOperations = invocationCount * operationsPerInvoke; setupAction(); ClockSpan clockSpan; GcCollect(gcMode); if (invocationCount == 1) { var chronometer = Chronometer.Start(); returnHolder = targetAction(); clockSpan = chronometer.Stop(); } else if (invocationCount < int.MaxValue) { int intInvocationCount = (int)invocationCount; var chronometer = Chronometer.Start(); RunAction(targetAction, intInvocationCount); clockSpan = chronometer.Stop(); } else { var chronometer = Chronometer.Start(); RunAction(targetAction, invocationCount); clockSpan = chronometer.Stop(); } multiInvokeReturnHolder = returnHolder; var measurement = new Measurement(0, mode, index, totalOperations, clockSpan.GetNanoseconds()); Console.WriteLine(measurement.ToOutputLine()); GcCollect(gcMode); return(measurement); }
private static string SetGcMode(string content, GcMode gcMode, IResolver resolver) { if (!gcMode.HasChanges) return content.Replace("$GC$", null); return content.Replace( "$GC$", $"\"runtimeOptions\": {{ \"configProperties\": {{ " + $"\"System.GC.Concurrent\": {gcMode.ResolveValue(GcMode.ConcurrentCharacteristic, resolver).ToLowerCase()}, " + $"\"System.GC.Server\": {gcMode.ResolveValue(GcMode.ServerCharacteristic, resolver).ToLowerCase()} }} }}, "); }
private static void GenerateGCSettings(XmlDocument xmlDocument, XmlNode runtimeElement, GcMode gcMode) { if (gcMode == new GcMode()) { return; } CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcConcurrent", "enabled", gcMode.Concurrent.ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcServer", "enabled", gcMode.Server.ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "GCCpuGroup", "enabled", gcMode.CpuGroups.ToLowerCase()); CreateNodeWithAttribute(xmlDocument, runtimeElement, "gcAllowVeryLargeObjects", "enabled", gcMode.AllowVeryLargeObjects.ToLowerCase()); }
private IConfig CreateConfig(GcMode gcMode) => ManualConfig.CreateEmpty().With(Job.Dry.With(gcMode));