예제 #1
0
        private ProcessStartInfo CreateStartInfo(BenchmarkCase benchmarkCase, ArtifactsPaths artifactsPaths,
                                                 string args, IResolver resolver, bool noAcknowledgments)
        {
            var start = new ProcessStartInfo
            {
                UseShellExecute        = false,
                RedirectStandardOutput = true,
                RedirectStandardInput  = !noAcknowledgments,
                RedirectStandardError  = false,         // #1629
                CreateNoWindow         = true,
                StandardOutputEncoding = Encoding.UTF8, // #1713
                WorkingDirectory       = null           // by default it's null
            };

            start.SetEnvironmentVariables(benchmarkCase, resolver);

            string exePath = artifactsPaths.ExecutablePath;

            var runtime = benchmarkCase.GetRuntime();

            // TODO: use resolver

            switch (runtime)
            {
            case ClrRuntime _:
            case CoreRuntime _:
            case NativeAotRuntime _:
                start.FileName  = exePath;
                start.Arguments = args;
                break;

            case MonoRuntime mono:
                start.FileName  = mono.CustomPath ?? "mono";
                start.Arguments = GetMonoArguments(benchmarkCase.Job, exePath, args, resolver);
                break;

            case WasmRuntime wasm:
                start.FileName = wasm.JavaScriptEngine;
                start.RedirectStandardInput = false;

                string main_js = runtime.RuntimeMoniker < RuntimeMoniker.WasmNet70 ? "main.js" : "test-main.js";

                start.Arguments        = $"{wasm.JavaScriptEngineArguments} {main_js} -- --run {artifactsPaths.ProgramName}.dll {args} ";
                start.WorkingDirectory = artifactsPaths.BinariesDirectoryPath;
                break;

            case MonoAotLLVMRuntime _:
                start.FileName         = exePath;
                start.Arguments        = args;
                start.WorkingDirectory = artifactsPaths.BinariesDirectoryPath;
                break;

            default:
                throw new NotSupportedException("Runtime = " + runtime);
            }
            return(start);
        }
예제 #2
0
        private static void GenerateAppConfig(Benchmark benchmark, ArtifactsPaths artifactsPaths, IResolver resolver)
        {
            string sourcePath = benchmark.Target.Type.GetTypeInfo().Assembly.Location + ".config";

            using (var source = File.Exists(sourcePath) ? new StreamReader(File.OpenRead(sourcePath)) : TextReader.Null)
                using (var destination = new System.IO.StreamWriter(File.Create(artifactsPaths.AppConfigPath), System.Text.Encoding.UTF8))
                {
                    AppConfigGenerator.Generate(benchmark.Job, source, destination, resolver);
                }
        }
예제 #3
0
        private static void GenerateAppConfig(BuildPartition buildPartition, ArtifactsPaths artifactsPaths)
        {
            string sourcePath = buildPartition.AssemblyLocation + ".config";

            using (var source = File.Exists(sourcePath) ? new StreamReader(File.OpenRead(sourcePath)) : TextReader.Null)
                using (var destination = new StreamWriter(File.Create(artifactsPaths.AppConfigPath), Encoding.UTF8))
                {
                    AppConfigGenerator.Generate(buildPartition.RepresentativeBenchmarkCase.Job, source, destination, buildPartition.Resolver);
                }
        }
예제 #4
0
        public GenerateResult GenerateProject(Benchmark benchmark, ILogger logger, string rootArtifactsFolderPath, IConfig config, IResolver resolver)
        {
            ArtifactsPaths artifactsPaths = null;

            try
            {
                artifactsPaths = GetArtifactsPaths(benchmark, config, rootArtifactsFolderPath);

                CopyAllRequiredFiles(benchmark, artifactsPaths);

                GenerateCode(benchmark, artifactsPaths);
                GenerateAppConfig(benchmark, artifactsPaths, resolver);
                GenerateProject(benchmark, artifactsPaths, resolver, logger);
                GenerateBuildScript(benchmark, artifactsPaths, resolver);

                return(GenerateResult.Success(artifactsPaths, GetArtifactsToCleanup(benchmark, artifactsPaths)));
            }
            catch (Exception ex)
            {
                return(GenerateResult.Failure(artifactsPaths, GetArtifactsToCleanup(benchmark, artifactsPaths), ex));
            }
        }
예제 #5
0
        public GenerateResult GenerateProject(BuildPartition buildPartition, ILogger logger, string rootArtifactsFolderPath)
        {
            ArtifactsPaths artifactsPaths = ArtifactsPaths.Empty;

            try
            {
                artifactsPaths = GetArtifactsPaths(buildPartition, rootArtifactsFolderPath);

                CopyAllRequiredFiles(artifactsPaths);

                GenerateCode(buildPartition, artifactsPaths);
                GenerateAppConfig(buildPartition, artifactsPaths);
                GenerateNuGetConfig(artifactsPaths);
                GenerateProject(buildPartition, artifactsPaths, logger);
                GenerateBuildScript(buildPartition, artifactsPaths);

                return(GenerateResult.Success(artifactsPaths, GetArtifactsToCleanup(artifactsPaths)));
            }
            catch (Exception ex)
            {
                return(GenerateResult.Failure(artifactsPaths, GetArtifactsToCleanup(artifactsPaths), ex));
            }
        }
예제 #6
0
 protected virtual void GenerateNuGetConfig(Benchmark benchmark, ArtifactsPaths artifactsPaths)
 {
 }
예제 #7
0
 protected virtual void CopyAllRequiredFiles(Benchmark benchmark, ArtifactsPaths artifactsPaths)
 {
 }
예제 #8
0
 protected abstract string[] GetArtifactsToCleanup(Benchmark benchmark, ArtifactsPaths artifactsPaths);
 private static void GenerateCode(Benchmark benchmark, ArtifactsPaths artifactsPaths)
 {
     File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(benchmark));
 }
예제 #10
0
 /// <summary>
 /// generates .csproj file with a reference to the project with benchmarks
 /// </summary>
 [PublicAPI] protected virtual void GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger)
 {
 }
예제 #11
0
 protected virtual void CopyAllRequiredFiles(ArtifactsPaths artifactsPaths) { }
예제 #12
0
 private static void GenerateCode(Benchmark benchmark, ArtifactsPaths artifactsPaths, IConfig config)
 {
     File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(benchmark, config));
 }
예제 #13
0
 private static void GenerateCode(BuildPartition buildPartition, ArtifactsPaths artifactsPaths)
 => File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(buildPartition));
예제 #14
0
        private void GenerateAppConfig(Benchmark benchmark, ArtifactsPaths artifactsPaths)
        {
            var sourcePath = benchmark.Target.Type.GetTypeInfo().Assembly.Location + ".config";

            using (var source = File.Exists(sourcePath) ? new StreamReader(File.OpenRead(sourcePath)) : TextReader.Null)
            using (var destination = new System.IO.StreamWriter(File.Create(artifactsPaths.AppConfigPath), System.Text.Encoding.UTF8))
            {
                AppConfigGenerator.Generate(benchmark.Job, source, destination);
            }
        }
예제 #15
0
        private void GenerateCode(Benchmark benchmark, ArtifactsPaths artifactsPaths)
        {
            var target = benchmark.Target;
            var isVoid = target.Method.ReturnType == typeof(void);

            var operationsPerInvoke = target.OperationsPerInvoke;

            var targetTypeNamespace = string.IsNullOrWhiteSpace(target.Type.Namespace)
                ? ""
                : $"using {target.Type.Namespace};";

            // As "using System;" is always included in the template, don't emit it again
            var emptyReturnTypeNamespace = target.Method.ReturnType == typeof(void) ||
                target.Method.ReturnType.Namespace == "System" ||
                string.IsNullOrWhiteSpace(target.Method.ReturnType.Namespace);
            var targetMethodReturnTypeNamespace = emptyReturnTypeNamespace
                ? ""
                : $"using {target.Method.ReturnType.Namespace};";

            var targetTypeName = target.Type.GetCorrectTypeName();
            var targetMethodName = target.Method.Name;

            var targetMethodReturnType = isVoid
                ? "void"
                : target.Method.ReturnType.GetCorrectTypeName();
            var idleMethodReturnType = isVoid || !target.Method.ReturnType.GetTypeInfo().IsValueType
                ? targetMethodReturnType
                : "int";
            var targetMethodResultHolder = isVoid
                ? ""
                : $"private {targetMethodReturnType} value;";
            var targetMethodHoldValue = isVoid
                ? ""
                : "value = ";
            var targetMethodDelegateType = isVoid
                ? "Action "
                : $"Func<{targetMethodReturnType}> ";
            var idleMethodDelegateType = isVoid
                ? "Action "
                : $"Func<{idleMethodReturnType}> ";

            // "Setup" or "Cleanup" methods are optional, so default to an empty delegate, so there is always something that can be invoked
            var setupMethodName = target.SetupMethod != null
                ? target.SetupMethod.Name
                : "() => { }";
            var cleanupMethodName = target.CleanupMethod != null
                ? target.CleanupMethod.Name
                : "() => { }";

            var idleImplementation = isVoid
                ? ""
                : $"return {(target.Method.ReturnType.GetTypeInfo().IsValueType ? "0" : "null")};";

            var paramsContent = string.Join("", benchmark.Parameters.Items.Select(parameter =>
                $"{(parameter.IsStatic ? "" : "instance.")}{parameter.Name} = {GetParameterValue(parameter.Value)};"));

            var targetBenchmarkTaskArguments = benchmark.Job.GenerateWithDefinitions();

            var contentTemplate = ResourceHelper.LoadTemplate("BenchmarkProgram.txt");
            var content = contentTemplate.
                Replace("$OperationsPerInvoke$", operationsPerInvoke.ToString()).
                Replace("$TargetTypeNamespace$", targetTypeNamespace).
                Replace("$TargetMethodReturnTypeNamespace$", targetMethodReturnTypeNamespace).
                Replace("$TargetTypeName$", targetTypeName).
                Replace("$TargetMethodName$", targetMethodName).
                Replace("$TargetMethodResultHolder$", targetMethodResultHolder).
                Replace("$TargetMethodDelegateType$", targetMethodDelegateType).
                Replace("$TargetMethodHoldValue$", targetMethodHoldValue).
                Replace("$TargetMethodReturnType$", targetMethodReturnType).
                Replace("$IdleMethodDelegateType$", idleMethodDelegateType).
                Replace("$IdleMethodReturnType$", idleMethodReturnType).
                Replace("$SetupMethodName$", setupMethodName).
                Replace("$CleanupMethodName$", cleanupMethodName).
                Replace("$IdleImplementation$", idleImplementation).
                Replace("$AdditionalLogic$", target.AdditionalLogic).
                Replace("$TargetBenchmarkTaskArguments$", targetBenchmarkTaskArguments).
                Replace("$ParamsContent$", paramsContent);

            File.WriteAllText(artifactsPaths.ProgramCodePath, content);
        }
예제 #16
0
 protected abstract void GenerateBuildScript(Benchmark benchmark, ArtifactsPaths artifactsPaths);
예제 #17
0
 protected virtual void GenerateProject(Benchmark benchmark, ArtifactsPaths artifactsPaths) { }
예제 #18
0
 protected virtual void GenerateProject(Benchmark benchmark, ArtifactsPaths artifactsPaths, IResolver resolver, ILogger logger)
 {
 }
예제 #19
0
 /// <summary>
 /// generates the C# source code with all required boilerplate.
 /// <remarks>You most probably do NOT need to override this method!!</remarks>
 /// </summary>
 [PublicAPI] protected virtual void GenerateCode(BuildPartition buildPartition, ArtifactsPaths artifactsPaths)
 => File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(buildPartition));
예제 #20
0
 protected abstract void GenerateBuildScript(Benchmark benchmark, ArtifactsPaths artifactsPaths, IResolver resolver);
예제 #21
0
 /// <summary>
 /// if you need to copy some extra files to make the benchmarks work you should override this method
 /// </summary>
 [PublicAPI] protected virtual void CopyAllRequiredFiles(ArtifactsPaths artifactsPaths)
 {
 }
예제 #22
0
 protected abstract void ArtifactCleanup(Benchmark benchmark, ArtifactsPaths artifactsPaths);
예제 #23
0
 protected abstract void Cleanup(ArtifactsPaths artifactsPaths);
예제 #24
0
 protected abstract void Cleanup(ArtifactsPaths artifactsPaths);
예제 #25
0
 protected virtual void GenerateProject(Benchmark benchmark, ArtifactsPaths artifactsPaths)
 {
 }
예제 #26
0
 /// <summary>
 /// returns a list of artifacts that should be removed after running the benchmarks
 /// </summary>
 [PublicAPI] protected abstract string[] GetArtifactsToCleanup(ArtifactsPaths artifactsPaths);
예제 #27
0
 private void GenerateCode(Benchmark benchmark, ArtifactsPaths artifactsPaths)
 {
     File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(benchmark));
 }
예제 #28
0
 /// <summary>
 /// generates NuGet.Config file to make sure that BDN is using the right NuGet feeds
 /// </summary>
 [PublicAPI] protected virtual void GenerateNuGetConfig(ArtifactsPaths artifactsPaths)
 {
 }
예제 #29
0
        private ExecuteResult Execute(BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, ILogger logger, ArtifactsPaths artifactsPaths,
                                      string args, IDiagnoser diagnoser, IResolver resolver, int launchIndex)
        {
            try
            {
                using (var process = new Process {
                    StartInfo = CreateStartInfo(benchmarkCase, artifactsPaths, args, resolver)
                })
                    using (var consoleExitHandler = new ConsoleExitHandler(process, logger))
                    {
                        var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmarkCase, benchmarkId);

                        diagnoser?.Handle(HostSignal.BeforeProcessStart, new DiagnoserActionParameters(process, benchmarkCase, benchmarkId));

                        return(Execute(process, benchmarkCase, loggerWithDiagnoser, logger, consoleExitHandler, launchIndex));
                    }
            }
            finally
            {
                diagnoser?.Handle(HostSignal.AfterProcessExit, new DiagnoserActionParameters(null, benchmarkCase, benchmarkId));
            }
        }
예제 #30
0
 /// <summary>
 /// generates a script can be used when debugging compilation issues
 /// </summary>
 [PublicAPI] protected abstract void GenerateBuildScript(BuildPartition buildPartition, ArtifactsPaths artifactsPaths);
 protected virtual void GenerateProject(Benchmark benchmark, ArtifactsPaths artifactsPaths, IResolver resolver) { }