Beispiel #1
0
 private IConfig CreateInProcessConfig(BenchmarkActionCodegen codegenMode, OutputLogger logger = null, IDiagnoser diagnoser = null)
 {
     return(new ManualConfig()
            .AddJob(Job.Dry.WithToolchain(new InProcessToolchain(TimeSpan.Zero, codegenMode, true)).WithInvocationCount(UnrollFactor).WithUnrollFactor(UnrollFactor))
            .AddLogger(logger ?? (Output != null ? new OutputLogger(Output) : ConsoleLogger.Default))
            .AddColumnProvider(DefaultColumnProviders.Instance));
 }
            public BenchmarkActionValueTask(object instance, MethodInfo method, BenchmarkActionCodegen codegenMode, int unrollFactor)
            {
                bool isOverhead = method == null;

                if (!isOverhead)
                {
                    startTaskCallback = CreateWorkload <Func <ValueTask <T> > >(instance, method);
                    callback          = ExecuteBlocking;
                }
                else
                {
                    callback = Overhead;
                }

                InvokeSingle = InvokeSingleHardcoded;

                if (UseFallbackCode(codegenMode, unrollFactor))
                {
                    unrolledCallback = Unroll(callback, unrollFactor);
                    InvokeMultiple   = InvokeMultipleHardcoded;
                }
                else
                {
                    InvokeMultiple = EmitInvokeMultiple(this, nameof(callback), nameof(result), unrollFactor);
                }
            }
Beispiel #3
0
            public BenchmarkActionTask(object instance, MethodInfo method, BenchmarkActionCodegen codegenMode, int unrollFactor)
            {
                bool isIdle = method == null;

                if (!isIdle)
                {
                    startTaskCallback = CreateMain <Func <Task> >(instance, method);
                    callback          = ExecuteBlocking;
                }
                else
                {
                    callback = Idle;
                }

                InvokeSingle = callback;

                if (UseFallbackCode(codegenMode, unrollFactor))
                {
                    unrolledCallback = Unroll(callback, unrollFactor);
                    InvokeMultiple   = InvokeMultipleHardcoded;
                }
                else
                {
                    InvokeMultiple = EmitInvokeMultiple(this, nameof(callback), null, unrollFactor);
                }
            }
Beispiel #4
0
        public static int Run(IHostApi hostApi, Benchmark benchmark, BenchmarkActionCodegen codegenMode)
        {
            bool isDiagnoserAttached = hostApi.IsDiagnoserAttached;

            // the first thing to do is to let diagnosers hook in before anything happens
            // so all jit-related diagnosers can catch first jit compilation!
            if (isDiagnoserAttached)
            {
                hostApi.BeforeAnythingElse();
            }

            try
            {
                // we are not using Runnable here in any direct way in order to avoid strong dependency Main<=>Runnable
                // which could cause the jitting/assembly loading to happen before we do anything
                // we have some jitting diagnosers and we want them to catch all the informations!!

                var inProcessRunnableTypeName = $"{typeof(InProcessRunner).FullName}+{nameof(Runnable)}";
                var type = typeof(InProcessRunner).GetTypeInfo().Assembly.GetType(inProcessRunnableTypeName);
                if (type == null)
                {
                    throw new InvalidOperationException($"Bug: type {inProcessRunnableTypeName} not found.");
                }

                type.GetMethod(nameof(Runnable.RunCore), BindingFlags.Public | BindingFlags.Static)
                .Invoke(null, new object[] { hostApi, benchmark, codegenMode });

                return(0);
            }
            catch (Exception ex)
            {
                hostApi.WriteLine(ex.ToString());
                return(-1);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Dispatch method that creates <see cref="BenchmarkAction"/> using
        /// <paramref name="targetMethod"/> or <paramref name="fallbackIdleSignature"/> to find correct implementation.
        /// Either <paramref name="targetMethod"/> or <paramref name="fallbackIdleSignature"/> should be not <c>null</c>.
        /// </summary>
        private static BenchmarkAction CreateCore(
            [NotNull] object instance,
            [CanBeNull] MethodInfo targetMethod,
            [CanBeNull] MethodInfo fallbackIdleSignature,
            BenchmarkActionCodegen codegenMode,
            int unrollFactor)
        {
            Type   resultType;
            object resultInstance;

            PrepareInstanceAndResultType(
                instance, targetMethod, fallbackIdleSignature, out resultInstance, out resultType);

            if (resultType == typeof(void))
            {
                return(new BenchmarkActionVoid(resultInstance, targetMethod, codegenMode, unrollFactor));
            }

            if (resultType == typeof(Task))
            {
                return(new BenchmarkActionTask(resultInstance, targetMethod, codegenMode, unrollFactor));
            }

            if (resultType.GetTypeInfo().IsGenericType)
            {
                var genericType = resultType.GetGenericTypeDefinition();
                var argType     = resultType.GenericTypeArguments[0];
                if (typeof(Task <>) == genericType)
                {
                    return(Create(
                               typeof(BenchmarkActionTask <>).MakeGenericType(argType),
                               resultInstance, targetMethod,
                               codegenMode, unrollFactor));
                }

                if (typeof(ValueTask <>).IsAssignableFrom(genericType))
                {
                    return(Create(
                               typeof(BenchmarkActionValueTask <>).MakeGenericType(argType),
                               resultInstance, targetMethod,
                               codegenMode, unrollFactor));
                }
            }

            if (targetMethod == null && resultType.GetTypeInfo().IsValueType)
            {
                // for Idle: we return int because creating bigger ValueType could take longer than benchmarked method itself.
                resultType = typeof(int);
            }

            return(Create(
                       typeof(BenchmarkAction <>).MakeGenericType(resultType),
                       resultInstance, targetMethod,
                       codegenMode, unrollFactor));
        }
        /// <summary>Initializes a new instance of the <see cref="InProcessExecutor" /> class.</summary>
        /// <param name="timeout">Timeout for the run.</param>
        /// <param name="codegenMode">Describes how benchmark action code is generated.</param>
        /// <param name="logOutput"><c>true</c> if the output should be logged.</param>
        public InProcessExecutor(TimeSpan timeout, BenchmarkActionCodegen codegenMode, bool logOutput)
        {
            if (timeout == TimeSpan.Zero)
            {
                timeout = DefaultTimeout;
            }

            ExecutionTimeout = timeout;
            CodegenMode      = codegenMode;
            LogOutput        = logOutput;
        }
            public BenchmarkAction(object instance, MethodInfo method, BenchmarkActionCodegen codegenMode, int unrollFactor)
            {
                callback     = CreateMainOrIdle <Func <T> >(instance, method, IdleStatic, IdleInstance);
                InvokeSingle = InvokeSingleHardcoded;

                if (UseFallbackCode(codegenMode, unrollFactor))
                {
                    unrolledCallback = Unroll(callback, unrollFactor);
                    InvokeMultiple   = InvokeMultipleHardcoded;
                }
                else
                {
                    InvokeMultiple = EmitInvokeMultiple(this, nameof(callback), nameof(result), unrollFactor);
                }
            }
            public BenchmarkActionVoid(object instance, MethodInfo method, BenchmarkActionCodegen codegenMode, int unrollFactor)
            {
                callback     = CreateWorkloadOrOverhead <Action>(instance, method, OverheadStatic, OverheadInstance);
                InvokeSingle = callback;

                if (UseFallbackCode(codegenMode, unrollFactor))
                {
                    unrolledCallback = Unroll(callback, unrollFactor);
                    InvokeMultiple   = InvokeMultipleHardcoded;
                }
                else
                {
                    InvokeMultiple = EmitInvokeMultiple(this, nameof(callback), null, unrollFactor);
                }
            }
Beispiel #9
0
            public BenchmarkActionVoid(
                object instance, MethodInfo method, BenchmarkActionCodegen codegenMode, int unrollFactor)
            {
                _callback    = CreateMainOrIdle <Action>(instance, method, IdleStatic, IdleInstance);
                InvokeSingle = _callback;

                if (UseFallbackCode(codegenMode, unrollFactor))
                {
                    _unrolledCallback = Unroll(_callback, unrollFactor);
                    InvokeMultiple    = InvokeMultipleHardcoded;
                }
                else
                {
                    InvokeMultiple = EmitInvokeMultiple(this, nameof(_callback), null, unrollFactor);
                }
            }
Beispiel #10
0
        public static int Run(IHost host, BenchmarkCase benchmarkCase, BenchmarkActionCodegen codegenMode, IConfig config)
        {
            // the first thing to do is to let diagnosers hook in before anything happens
            // so all jit-related diagnosers can catch first jit compilation!
            host.BeforeAnythingElse();

            try
            {
                // we are not using Runnable here in any direct way in order to avoid strong dependency Main<=>Runnable
                // which could cause the jitting/assembly loading to happen before we do anything
                // we have some jitting diagnosers and we want them to catch all the informations!!

                var inProcessRunnableTypeName = $"{typeof(InProcessRunner).FullName}+{nameof(Runnable)}";
                var type = typeof(InProcessRunner).GetTypeInfo().Assembly.GetType(inProcessRunnableTypeName);
                if (type == null)
                {
                    throw new InvalidOperationException($"Bug: type {inProcessRunnableTypeName} not found.");
                }

                type.GetMethod(nameof(Runnable.RunCore), BindingFlags.Public | BindingFlags.Static)
                .Invoke(null, new object[] { host, benchmarkCase, codegenMode, config });

                return(0);
            }
            catch (Exception oom) when(oom is OutOfMemoryException || oom is TargetInvocationException reflection && reflection.InnerException is OutOfMemoryException)
            {
                host.WriteLine();
                host.WriteLine("OutOfMemoryException!");
                host.WriteLine("BenchmarkDotNet continues to run additional iterations until desired accuracy level is achieved. It's possible only if the benchmark method doesn't have any side-effects.");
                host.WriteLine("If your benchmark allocates memory and keeps it alive, you are creating a memory leak.");
                host.WriteLine("You should redesign your benchmark and remove the side-effects. You can use `OperationsPerInvoke`, `IterationSetup` and `IterationCleanup` to do that.");
                host.WriteLine();
                host.WriteLine(oom.ToString());

                return(-1);
            }
            catch (Exception ex)
            {
                host.WriteLine();
                host.WriteLine(ex.ToString());
                return(-1);
            }
            finally
            {
                host.AfterAll();
            }
        }
Beispiel #11
0
            public BenchmarkActionValueTask(
                object instance, MethodInfo method, BenchmarkActionCodegen codegenMode, int unrollFactor)
            {
                _startTaskCallback = CreateMainOrIdle <Func <ValueTask <T> > >(instance, method, IdleStatic, IdleInstance);
                _callback          = ExecuteBlocking;
                InvokeSingle       = InvokeSingleHardcoded;

                if (UseFallbackCode(codegenMode, unrollFactor))
                {
                    _unrolledCallback = Unroll(_callback, unrollFactor);
                    InvokeMultiple    = InvokeMultipleHardcoded;
                }
                else
                {
                    InvokeMultiple = EmitInvokeMultiple(this, nameof(_callback), nameof(_result), unrollFactor);
                }
            }
Beispiel #12
0
            public static void RunCore(IHost host, BenchmarkCase benchmarkCase, BenchmarkActionCodegen codegenMode, IConfig config)
            {
                var target       = benchmarkCase.Descriptor;
                var job          = benchmarkCase.Job; // TODO: filter job (same as SourceCodePresenter does)?
                int unrollFactor = benchmarkCase.Job.ResolveValue(RunMode.UnrollFactorCharacteristic, EnvironmentResolver.Instance);

                // DONTTOUCH: these should be allocated together
                var instance               = Activator.CreateInstance(benchmarkCase.Descriptor.Type);
                var workloadAction         = BenchmarkActionFactory.CreateWorkload(target, instance, codegenMode, unrollFactor);
                var overheadAction         = BenchmarkActionFactory.CreateOverhead(target, instance, codegenMode, unrollFactor);
                var globalSetupAction      = BenchmarkActionFactory.CreateGlobalSetup(target, instance);
                var globalCleanupAction    = BenchmarkActionFactory.CreateGlobalCleanup(target, instance);
                var iterationSetupAction   = BenchmarkActionFactory.CreateIterationSetup(target, instance);
                var iterationCleanupAction = BenchmarkActionFactory.CreateIterationCleanup(target, instance);
                var dummy1 = BenchmarkActionFactory.CreateDummy();
                var dummy2 = BenchmarkActionFactory.CreateDummy();
                var dummy3 = BenchmarkActionFactory.CreateDummy();

                FillMembers(instance, benchmarkCase);

                host.WriteLine();
                foreach (string infoLine in BenchmarkEnvironmentInfo.GetCurrent().ToFormattedString())
                {
                    host.WriteLine("// {0}", infoLine);
                }
                host.WriteLine("// Job: {0}", job.DisplayInfo);
                host.WriteLine();

                var engineParameters = new EngineParameters
                {
                    Host = host,
                    WorkloadActionNoUnroll = invocationCount =>
                    {
                        for (int i = 0; i < invocationCount; i++)
                        {
                            workloadAction.InvokeSingle();
                        }
                    },
                    WorkloadActionUnroll   = workloadAction.InvokeMultiple,
                    Dummy1Action           = dummy1.InvokeSingle,
                    Dummy2Action           = dummy2.InvokeSingle,
                    Dummy3Action           = dummy3.InvokeSingle,
                    OverheadActionNoUnroll = invocationCount =>
                    {
                        for (int i = 0; i < invocationCount; i++)
                        {
                            overheadAction.InvokeSingle();
                        }
                    },
                    OverheadActionUnroll   = overheadAction.InvokeMultiple,
                    GlobalSetupAction      = globalSetupAction.InvokeSingle,
                    GlobalCleanupAction    = globalCleanupAction.InvokeSingle,
                    IterationSetupAction   = iterationSetupAction.InvokeSingle,
                    IterationCleanupAction = iterationCleanupAction.InvokeSingle,
                    TargetJob           = job,
                    OperationsPerInvoke = target.OperationsPerInvoke,
                    MeasureGcStats      = config.HasMemoryDiagnoser(),
                    BenchmarkName       = FullNameProvider.GetBenchmarkName(benchmarkCase)
                };

                using (var engine = job
                                    .ResolveValue(InfrastructureMode.EngineFactoryCharacteristic, InfrastructureResolver.Instance)
                                    .CreateReadyToRun(engineParameters))
                {
                    var results = engine.Run();

                    host.ReportResults(results); // printing costs memory, do this after runs
                }
            }
 protected static bool UseFallbackCode(BenchmarkActionCodegen codegenMode, int unrollFactor) =>
 unrollFactor <= 1 || codegenMode == BenchmarkActionCodegen.DelegateCombine;
 /// <summary>Initializes a new instance of the <see cref="InProcessToolchain" /> class.</summary>
 /// <param name="timeout">Timeout for the run.</param>
 /// <param name="codegenMode">Describes how benchmark action code is generated.</param>
 /// <param name="logOutput"><c>true</c> if the output should be logged.</param>
 public InProcessToolchain(TimeSpan timeout, BenchmarkActionCodegen codegenMode, bool logOutput)
 {
     Generator = new InProcessGenerator();
     Builder   = new InProcessBuilder();
     Executor  = new InProcessExecutor(timeout, codegenMode, logOutput);
 }
 /// <summary>Creates idle benchmark action.</summary>
 /// <param name="target">Target info.</param>
 /// <param name="instance">Instance of target.</param>
 /// <param name="codegenMode">Describes how benchmark action code is generated.</param>
 /// <param name="unrollFactor">Unroll factor.</param>
 /// <returns>Idle benchmark action.</returns>
 public static BenchmarkAction CreateIdle(Target target, object instance, BenchmarkActionCodegen codegenMode, int unrollFactor) =>
 CreateCore(instance, null, target.Method, codegenMode, unrollFactor);
Beispiel #16
0
            public static void RunCore(IHostApi hostApi, Benchmark benchmark, BenchmarkActionCodegen codegenMode)
            {
                var target       = benchmark.Target;
                var job          = benchmark.Job;        // TODO: filter job (same as SourceCodePresenter does)?
                var unrollFactor = benchmark.Job.ResolveValue(RunMode.UnrollFactorCharacteristic, EnvResolver.Instance);
                // var dummyUnrollFactor = 1 << 6; // TODO: as arg to CreateDummy()?

                // DONTTOUCH: these should be allocated together
                var instance      = Activator.CreateInstance(benchmark.Target.Type);
                var mainAction    = BenchmarkActionFactory.CreateRun(target, instance, codegenMode, unrollFactor);
                var idleAction    = BenchmarkActionFactory.CreateIdle(target, instance, codegenMode, unrollFactor);
                var setupAction   = BenchmarkActionFactory.CreateSetup(target, instance);
                var cleanupAction = BenchmarkActionFactory.CreateCleanup(target, instance);
                var dummy1        = BenchmarkActionFactory.CreateDummy();
                var dummy2        = BenchmarkActionFactory.CreateDummy();
                var dummy3        = BenchmarkActionFactory.CreateDummy();

                FillProperties(instance, benchmark);

                hostApi.WriteLine();
                foreach (var infoLine in BenchmarkEnvironmentInfo.GetCurrent().ToFormattedString())
                {
                    hostApi.WriteLine("// {0}", infoLine);
                }
                hostApi.WriteLine("// Job: {0}", job.DisplayInfo);
                hostApi.WriteLine();

                var engineParameters = new EngineParameters
                {
                    //HostApi = hostApi,
                    IsDiagnoserAttached = hostApi.IsDiagnoserAttached,
                    MainAction          = mainAction.InvokeMultiple,
                    Dummy1Action        = dummy1.InvokeSingle,
                    Dummy2Action        = dummy2.InvokeSingle,
                    Dummy3Action        = dummy3.InvokeSingle,
                    IdleAction          = idleAction.InvokeMultiple,
                    SetupAction         = setupAction.InvokeSingle,
                    CleanupAction       = cleanupAction.InvokeSingle,
                    TargetJob           = job,
                    OperationsPerInvoke = target.OperationsPerInvoke
                };

                var engine = job
                             .ResolveValue(InfrastructureMode.EngineFactoryCharacteristic, InfrastructureResolver.Instance)
                             .Create(engineParameters);

                engine.PreAllocate();

                setupAction.InvokeSingle();

                if (job.ResolveValue(RunMode.RunStrategyCharacteristic, EngineResolver.Instance)
                    != RunStrategy.ColdStart)
                {
                    engine.Jitting();                     // does first call to main action, must be executed after setup()!
                }
                if (hostApi.IsDiagnoserAttached)
                {
                    hostApi.AfterSetup();
                }

                var results = engine.Run();

                if (hostApi.IsDiagnoserAttached)
                {
                    hostApi.BeforeCleanup();
                }
                cleanupAction.InvokeSingle();

                hostApi.Print(results);                 // printing costs memory, do this after runs
            }
Beispiel #17
0
 /// <summary>Creates idle benchmark action.</summary>
 /// <param name="descriptor">Descriptor info.</param>
 /// <param name="instance">Instance of target.</param>
 /// <param name="codegenMode">Describes how benchmark action code is generated.</param>
 /// <param name="unrollFactor">Unroll factor.</param>
 /// <returns>Idle benchmark action.</returns>
 public static BenchmarkAction CreateOverhead(Descriptor descriptor, object instance, BenchmarkActionCodegen codegenMode, int unrollFactor) =>
 CreateCore(instance, null, descriptor.WorkloadMethod, codegenMode, unrollFactor);
Beispiel #18
0
 /// <summary>Helper to enforce .ctor signature.</summary>
 private static BenchmarkActionBase Create(Type actionType, object instance, MethodInfo method, BenchmarkActionCodegen codegenMode, int unrollFactor) =>
 (BenchmarkActionBase)Activator.CreateInstance(actionType, instance, method, codegenMode, unrollFactor);
Beispiel #19
0
            public static void RunCore(IHost host, Benchmark benchmark, BenchmarkActionCodegen codegenMode, IConfig config)
            {
                var target       = benchmark.Target;
                var job          = benchmark.Job; // TODO: filter job (same as SourceCodePresenter does)?
                var unrollFactor = benchmark.Job.ResolveValue(RunMode.UnrollFactorCharacteristic, EnvResolver.Instance);

                // DONTTOUCH: these should be allocated together
                var instance               = Activator.CreateInstance(benchmark.Target.Type);
                var mainAction             = BenchmarkActionFactory.CreateRun(target, instance, codegenMode, unrollFactor);
                var idleAction             = BenchmarkActionFactory.CreateIdle(target, instance, codegenMode, unrollFactor);
                var globalSetupAction      = BenchmarkActionFactory.CreateGlobalSetup(target, instance);
                var globalCleanupAction    = BenchmarkActionFactory.CreateGlobalCleanup(target, instance);
                var iterationSetupAction   = BenchmarkActionFactory.CreateIterationSetup(target, instance);
                var iterationCleanupAction = BenchmarkActionFactory.CreateIterationCleanup(target, instance);
                var dummy1 = BenchmarkActionFactory.CreateDummy();
                var dummy2 = BenchmarkActionFactory.CreateDummy();
                var dummy3 = BenchmarkActionFactory.CreateDummy();

                FillMembers(instance, benchmark);

                host.WriteLine();
                foreach (var infoLine in BenchmarkEnvironmentInfo.GetCurrent().ToFormattedString())
                {
                    host.WriteLine("// {0}", infoLine);
                }
                host.WriteLine("// Job: {0}", job.DisplayInfo);
                host.WriteLine();

                var engineParameters = new EngineParameters
                {
                    Host                   = host,
                    MainAction             = mainAction.InvokeMultiple,
                    Dummy1Action           = dummy1.InvokeSingle,
                    Dummy2Action           = dummy2.InvokeSingle,
                    Dummy3Action           = dummy3.InvokeSingle,
                    IdleAction             = idleAction.InvokeMultiple,
                    GlobalSetupAction      = globalSetupAction.InvokeSingle,
                    GlobalCleanupAction    = globalCleanupAction.InvokeSingle,
                    IterationSetupAction   = iterationSetupAction.InvokeSingle,
                    IterationCleanupAction = iterationCleanupAction.InvokeSingle,
                    TargetJob              = job,
                    OperationsPerInvoke    = target.OperationsPerInvoke,
                    MeasureGcStats         = config.HasMemoryDiagnoser()
                };

                var engine = job
                             .ResolveValue(InfrastructureMode.EngineFactoryCharacteristic, InfrastructureResolver.Instance)
                             .Create(engineParameters);

                globalSetupAction.InvokeSingle();
                iterationSetupAction.InvokeSingle();

                if (job.ResolveValue(RunMode.RunStrategyCharacteristic, EngineResolver.Instance).NeedsJitting())
                {
                    engine.Jitting(); // does first call to main action, must be executed after setup()!
                }
                iterationCleanupAction.InvokeSingle();

                var results = engine.Run();

                globalCleanupAction.InvokeSingle();

                host.ReportResults(results); // printing costs memory, do this after runs
            }