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); }
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); } }
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); } }
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)); } }
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)); } }
protected virtual void GenerateNuGetConfig(Benchmark benchmark, ArtifactsPaths artifactsPaths) { }
protected virtual void CopyAllRequiredFiles(Benchmark benchmark, ArtifactsPaths artifactsPaths) { }
protected abstract string[] GetArtifactsToCleanup(Benchmark benchmark, ArtifactsPaths artifactsPaths);
private static void GenerateCode(Benchmark benchmark, ArtifactsPaths artifactsPaths) { File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(benchmark)); }
/// <summary> /// generates .csproj file with a reference to the project with benchmarks /// </summary> [PublicAPI] protected virtual void GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger) { }
protected virtual void CopyAllRequiredFiles(ArtifactsPaths artifactsPaths) { }
private static void GenerateCode(Benchmark benchmark, ArtifactsPaths artifactsPaths, IConfig config) { File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(benchmark, config)); }
private static void GenerateCode(BuildPartition buildPartition, ArtifactsPaths artifactsPaths) => File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(buildPartition));
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); } }
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); }
protected abstract void GenerateBuildScript(Benchmark benchmark, ArtifactsPaths artifactsPaths);
protected virtual void GenerateProject(Benchmark benchmark, ArtifactsPaths artifactsPaths) { }
protected virtual void GenerateProject(Benchmark benchmark, ArtifactsPaths artifactsPaths, IResolver resolver, ILogger logger) { }
/// <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));
protected abstract void GenerateBuildScript(Benchmark benchmark, ArtifactsPaths artifactsPaths, IResolver resolver);
/// <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) { }
protected abstract void ArtifactCleanup(Benchmark benchmark, ArtifactsPaths artifactsPaths);
protected abstract void Cleanup(ArtifactsPaths artifactsPaths);
/// <summary> /// returns a list of artifacts that should be removed after running the benchmarks /// </summary> [PublicAPI] protected abstract string[] GetArtifactsToCleanup(ArtifactsPaths artifactsPaths);
private void GenerateCode(Benchmark benchmark, ArtifactsPaths artifactsPaths) { File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(benchmark)); }
/// <summary> /// generates NuGet.Config file to make sure that BDN is using the right NuGet feeds /// </summary> [PublicAPI] protected virtual void GenerateNuGetConfig(ArtifactsPaths artifactsPaths) { }
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)); } }
/// <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) { }