Benchmarkdotnet: System.NotSupportedException: Line must start with GC

Created on 26 Nov 2018  路  5Comments  路  Source: dotnet/BenchmarkDotNet

This is my 1st day using BenchmarkDotNet 0.11.3and I must say I'm liking the overall experience, however I've run into an issue that puzzles me.

Program.cs

class Program
    {
        static void Main(string[] args) => BenchmarkSwitcher
            .FromAssembly(typeof(Program).Assembly)
            .Run(args, DefaultConfig.Instance.With(new MemoryDiagnoser()));
    }

My benchmarked methods contain both the [Benchmark] and [MemoryDiagnoser] attributes.

[BenchmarkCategory("Logging")]
    [CoreJob]
    [MarkdownExporter, HtmlExporter, CsvExporter()]
    [SimpleJob(RunStrategy.Throughput, warmupCount: 1, launchCount: 1, targetCount: 1)]
    public class MyLoggingAsyncBenchmark
    {
        private const string ConfigFile = "logging-async-benchmark.json";
        public const string LogMessage = "Benchmark Log Message";

        [GlobalSetup]
        public void Setup()
        {
            var config = new ConfigurationBuilder()
                .AddJsonFile(ConfigFile)
                .Build();
            var logger = new LoggerConfiguration()
                .ConfigureSerilog(config)
                .CreateLogger();            
            Log.SetLoggerFactory(new LoggerFactory(logger));            // this is our custom log wrapper around serilog
        }

        [GlobalCleanup]
        public void Cleanup()
        {
        }       

        [Benchmark]
        [MemoryDiagnoser]
        public void LogFasitCoreLoggingInformation()
        {
            Log.Information<ILogBenchmark>().LogStuff();
        }
    }

When the benchmark suite is about to be finished, the process is crashing with the following exception.

Unhandled Exception: System.NotSupportedException: Line must start with GC:
   at BenchmarkDotNet.Engines.GcStats.Parse(String line)
   at BenchmarkDotNet.Running.BenchmarkRunner.Execute(ILogger logger, BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, IToolchain toolchain, BuildResult buildResult, IConfig config, IResolver resolver)
   at BenchmarkDotNet.Running.BenchmarkRunner.RunCore(BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, ILogger logger, ReadOnlyConfig config, IResolver resolver, BuildResult buildResult)

   at BenchmarkDotNet.Running.BenchmarkRunner.Run(BenchmarkRunInfo benchmarkRunInfo, Dictionary`2 buildResults, IResolver resolver, ILogger logger, List`1 artifactsToCleanup, String rootArtifactsFolderPath, StartedClock& runChronometer)
   at BenchmarkDotNet.Running.BenchmarkRunner.Run(BenchmarkRunInfo[] benchmarkRunInfos, IConfig commonSettingsConfig)
   at BenchmarkDotNet.Running.BenchmarkSwitcher.Run(String[] args, IConfig config)
   at My.Benchmarks.Program.Main(String[] args) in C:\Checkout\My.Project\src\My.Benchmarks\Program.cs:line 9

I haven't yet found any mention of the behavior in the docs, so I'd apreciate an explanation on what is happening here

Diagnosers bug

Most helpful comment

@morgan-kn I just hit this bug and solved it. The problem was when the user was writing something to output in [GlobalCleanup] and we were trying to parse this output instead of the output written by MemoryDiagnoser

All 5 comments

Hello @mmisztal1980

I am surprised that nobody else has hit this bug so far.

Could you try to use [MemoryDiagnoser] not for the method, but for the type? (it's just a workaround for now)

Also, if your benchmarks projects targets only .NET Core you don't need to use [CoreJob]. And [GlobalSetup] does not require a [GlobalCleanup] (it's empty in your example, I am not sure if you did not remove some code for the brevity

Same error when I've written something in console.
And well if I do not write to console

Hello @mmisztal1980
Could you please provide here your output (BenchmarkDotNet.Artifacts/result/*.log)?

@morgan-kn I just hit this bug and solved it. The problem was when the user was writing something to output in [GlobalCleanup] and we were trying to parse this output instead of the output written by MemoryDiagnoser

Yeah, I found out this, too. I reproduced this by adding into benchmark itself this line:
AppDomain.CurrentDomain.ProcessExit += (sender, e) => Console.WriteLine("Test");
Just wanted to make sure that user had a redundant line in his output.
Thanks, @adamsitnik =)

Was this page helpful?
0 / 5 - 0 ratings