private void RunCore( Benchmark benchmark, IRunnableBenchmark runnableBenchmark, ILogger logger, IDiagnoser diagnoser, BlockingStream outputStream) { var outputWriter = new StreamWriter(outputStream); var process = Process.GetCurrentProcess(); try { runnableBenchmark.Init(benchmark, outputWriter); diagnoser?.ProcessStarted(process); runnableBenchmark.Run(); diagnoser?.AfterBenchmarkHasRun(benchmark, process); } catch (Exception ex) { logger.WriteLineError($"// ! {GetType().Name}, exception: {ex}"); } finally { diagnoser?.ProcessStopped(process); outputWriter.Flush(); outputStream.CompleteWriting(); } }
private ExecuteResult Execute(Process process, Benchmark benchmark, SynchronousProcessOutputLoggerWithDiagnoser loggerWithDiagnoser, IDiagnoser compositeDiagnoser, ILogger logger) { consoleHandler.SetProcess(process); process.Start(); compositeDiagnoser?.ProcessStarted(process); process.EnsureHighPriority(logger); if (!benchmark.Job.Affinity.IsAuto) { process.EnsureProcessorAffinity(benchmark.Job.Affinity.Value); } loggerWithDiagnoser.ProcessInput(); process.WaitForExit(); // should we add timeout here? compositeDiagnoser?.ProcessStopped(process); if (process.ExitCode == 0) { return new ExecuteResult(true, loggerWithDiagnoser.Lines); } return new ExecuteResult(true, new string[0]); }
/// <summary>Executes the specified benchmark.</summary> /// <param name="buildResult">The build result.</param> /// <param name="benchmark">The benchmark.</param> /// <param name="logger">The logger.</param> /// <param name="resolver">The resolver.</param> /// <param name="diagnoser">The diagnoser.</param> /// <returns>Execution result.</returns> public ExecuteResult Execute( BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser diagnoser = null) { // TODO: preallocate buffer for output (no direct logging)? var hostApi = new InProcessHostApi(benchmark, LogOutput ? logger : null, diagnoser); int exitCode = -1; var runThread = new Thread(() => exitCode = ExecuteCore(hostApi, benchmark, logger)); if (benchmark.Target.Method.GetCustomAttributes <STAThreadAttribute>(false).Any()) { // TODO: runThread.SetApartmentState(ApartmentState.STA); } runThread.IsBackground = true; var timeout = HostEnvironmentInfo.GetCurrent().HasAttachedDebugger ? _underDebuggerTimeout : ExecutionTimeout; runThread.Start(); // TODO: to timespan overload (not available for .Net Core for now). if (!runThread.Join((int)timeout.TotalMilliseconds)) { throw new InvalidOperationException( $"Benchmark {benchmark.DisplayInfo} takes to long to run. " + "Prefer to use out-of-process toolchains for long-running benchmarks."); } return(GetExecutionResult(hostApi.RunResults, exitCode, logger)); }
private IConfig CreateConfig(Jit jit, Platform platform, Runtime runtime, IDiagnoser disassemblyDiagnoser) => ManualConfig.CreateEmpty() .With(Job.ShortRun.With(jit).With(platform).With(runtime)) .With(DefaultConfig.Instance.GetLoggers().ToArray()) .With(DefaultColumnProviders.Instance) .With(disassemblyDiagnoser) .With(new OutputLogger(Output));
private ExecuteResult Execute(Process process, Benchmark benchmark, SynchronousProcessOutputLoggerWithDiagnoser loggerWithDiagnoser, IDiagnoser compositeDiagnoser, ILogger logger) { consoleHandler.SetProcess(process); process.Start(); compositeDiagnoser?.ProcessStarted(process); process.EnsureHighPriority(logger); if (!benchmark.Job.Env.Affinity.IsDefault) { process.EnsureProcessorAffinity(benchmark.Job.Env.Affinity.SpecifiedValue); } loggerWithDiagnoser.ProcessInput(); process.WaitForExit(); // should we add timeout here? compositeDiagnoser?.ProcessStopped(process); if (process.ExitCode == 0) { return(new ExecuteResult(true, process.ExitCode, loggerWithDiagnoser.LinesWithResults, loggerWithDiagnoser.LinesWithExtraOutput)); } return(new ExecuteResult(true, process.ExitCode, new string[0], new string[0])); }
public ExecuteParameters(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IConfig config, IDiagnoser diagnoser = null) { BuildResult = buildResult; Benchmark = benchmark; Logger = logger; Resolver = resolver; Config = config; Diagnoser = diagnoser; }
private void createNewDiagnoser() { FlipFunction flip = new FlipFunction(); TimeSpan x = new TimeSpan(0, 1, 0); IterativeDeepening salgo = new IterativeDeepening(flip, x); ConesAlgorithm algo = new ConesAlgorithm(salgo); this.Diagnoser = algo; }
public ExecuteParameters(BuildResult buildResult, BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, ILogger logger, IResolver resolver, IDiagnoser diagnoser = null) { BuildResult = buildResult; BenchmarkCase = benchmarkCase; BenchmarkId = benchmarkId; Logger = logger; Resolver = resolver; Diagnoser = diagnoser; }
private IConfig CreateConfig(IDiagnoser diagnoser) { return(ManualConfig.CreateEmpty() .With(Job.ShortRun.WithGcForce(false)) .With(DefaultConfig.Instance.GetLoggers().ToArray()) .With(DefaultColumnProviders.Instance) .With(diagnoser) .With(new OutputLogger(output))); }
private IConfig CreateConfig(Jit jit, Platform platform, Runtime runtime, IDiagnoser disassemblyDiagnoser, RunStrategy runStrategy) => ManualConfig.CreateEmpty() .AddJob(Job.Dry.WithJit(jit) .WithPlatform(platform) .WithRuntime(runtime) .WithStrategy(runStrategy)) .AddLogger(DefaultConfig.Instance.GetLoggers().ToArray()) .AddColumnProvider(DefaultColumnProviders.Instance) .AddDiagnoser(disassemblyDiagnoser) .AddLogger(new OutputLogger(Output));
public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser compositeDiagnoser = null) { var exePath = buildResult.ArtifactsPaths.ExecutablePath; var args = compositeDiagnoser == null ? string.Empty : Engine.Signals.DiagnoserIsAttachedParam; if (!File.Exists(exePath)) { return new ExecuteResult(false, -1, new string[0], new string[0]); } return Execute(benchmark, logger, exePath, null, args, compositeDiagnoser, resolver); }
public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IDiagnoser compositeDiagnoser = null) { var exePath = buildResult.ExecutablePath; var args = string.Empty; if (!File.Exists(exePath)) { return new ExecuteResult(false, new string[0]); } return Execute(benchmark, logger, exePath, null, args, compositeDiagnoser); }
private static string BuildArgs(IDiagnoser diagnoser, string executableName) { var args = new StringBuilder(50); args.AppendFormat(executableName); if (diagnoser != null) { args.Append($" {Engine.Signals.DiagnoserIsAttachedParam}"); } return(args.ToString()); }
public Simulator(IDiagnoser Algorithm) { Diagnoser = Algorithm; if (Diagnoser != null && Diagnoser is DiagnosesSearcher) { this.gateFunc = ((DiagnosesSearcher)Diagnoser).function; } else { this.gateFunc = new FlipFunction(); } MOCreator = new ModelObservationCreator(); }
public Simulator(IDiagnoser Algorithm) { Diagnoser = Algorithm; if (Diagnoser != null && Diagnoser is DiagnosesSearcher) { gateFunc = ((DiagnosesSearcher)Diagnoser).function; } else { gateFunc = new FlipFunction(); } parser = new ISCASParser(); }
public SynchronousProcessOutputLoggerWithDiagnoser(ILogger logger, Process process, IDiagnoser diagnoser, Benchmark benchmark) { if (!process.StartInfo.RedirectStandardOutput) { throw new NotSupportedException("set RedirectStandardOutput to true first"); } this.logger = logger; this.process = process; this.diagnoser = diagnoser; this.benchmark = benchmark; Lines = new List <string>(); }
private IConfig CreateConfig(IDiagnoser diagnoser, int targetCount) { return(ManualConfig.CreateEmpty() .With( new Job(Job.Dry) { Run = { LaunchCount = 1, WarmupCount = 1, TargetCount = targetCount }, Env = { Gc = { Force = false } } }) .With(DefaultConfig.Instance.GetLoggers().ToArray()) .With(DefaultColumnProviders.Instance) .With(diagnoser) .With(new OutputLogger(output))); }
public SynchronousProcessOutputLoggerWithDiagnoser(ILogger logger, Process process, IDiagnoser diagnoser, Benchmark benchmark) { if (!process.StartInfo.RedirectStandardOutput) { throw new NotSupportedException("set RedirectStandardOutput to true first"); } this.logger = logger; this.process = process; this.diagnoser = diagnoser; this.benchmark = benchmark; Lines = new List<string>(); }
private IConfig CreateConfig(IDiagnoser diagnoser, int targetCount) { return(ManualConfig.CreateEmpty() .With( Job.Dry .WithLaunchCount(1) .WithWarmupCount(1) .WithTargetCount(targetCount) .WithGcForce(false)) .With(DefaultConfig.Instance.GetLoggers().ToArray()) .With(DefaultColumnProviders.Instance) .With(diagnoser) .With(new OutputLogger(output))); }
private ExecuteResult ExecuteImpl(Process process, string exeName, Benchmark benchmark, ILogger logger, IDiagnoser compositeDiagnoser = null) { process.PriorityClass = ProcessPriorityClass.High; if (!benchmark.Job.Affinity.IsAuto) process.ProcessorAffinity = new IntPtr(benchmark.Job.Affinity.Value); var lines = new List<string>(); string line; while ((line = process.StandardOutput.ReadLine()) != null) { logger?.WriteLine(line); if (!line.StartsWith("//") && !string.IsNullOrEmpty(line)) lines.Add(line); if (compositeDiagnoser == null) continue; // This is important so the Diagnoser can know the [Benchmark] methods will have run and (e.g.) it can do a Memory Dump if (diagnosticsAlreadyRun == false && line.StartsWith(IterationMode.MainWarmup.ToString())) { try { compositeDiagnoser.AfterBenchmarkHasRun(benchmark, process); } finally { // Always set this, even if something went wrong, otherwise we will try on every run of a benchmark batch diagnosticsAlreadyRun = true; } } } if (process.HasExited && process.ExitCode != 0) { if (logger != null) { logger.WriteError( $"Something bad happened during the execution of {exeName}. Try to run the benchmark again using an AnyCPU application\n"); } else { if (exeName.ToLowerInvariant() == "msbuild") Console.WriteLine("Build failed"); } return new ExecuteResult(true, new string[0]); } return new ExecuteResult(true, lines); }
// TODO: replace outputStream with something better? // WAITINGFOR: https://github.com/PerfDotNet/BenchmarkDotNet/issues/177 /// <summary>Executes the specified benchmark.</summary> /// <param name="buildResult">The build result.</param> /// <param name="benchmark">The benchmark.</param> /// <param name="logger">The logger.</param> /// <param name="diagnoser">The diagnoser.</param> /// <returns>Execution result.</returns> public ExecuteResult Execute( BuildResult buildResult, Benchmark benchmark, ILogger logger, IDiagnoser diagnoser = null) { var runnableBenchmark = RunnableBenchmarkFactory.Create(benchmark); var outputStream = new BlockingStream(10000); var runThread = new Thread( () => RunCore(benchmark, runnableBenchmark, logger, diagnoser, outputStream)); RunWithPriority( ProcessPriorityClass.RealTime, benchmark.Job.Affinity, logger, () => { runThread.IsBackground = true; runThread.Priority = ThreadPriority.Highest; runThread.Start(); if (!runThread.Join(ExecutionTimeout)) { throw new InvalidOperationException( "Benchmark takes to long to run. " + "Prefer to use out-of-process toolchains for long-running benchmarks."); } }); var outputReader = new StreamReader(outputStream); var lines = new List <string>(); string line; while ((line = outputReader.ReadLine()) != null) { if (LogOutput) { logger.WriteLine(line); } if (!line.StartsWith("//") && !string.IsNullOrEmpty(line)) { lines.Add(line); } } return(new ExecuteResult(true, lines.ToArray())); }
/// <summary>Creates a new instance of <see cref="InProcessHost"/>.</summary> /// <param name="benchmarkCase">Current benchmark.</param> /// <param name="logger">Logger for informational output.</param> /// <param name="diagnoser">Diagnosers, if attached.</param> /// <param name="config">Current config.</param> public InProcessHost(BenchmarkCase benchmarkCase, ILogger logger, IDiagnoser diagnoser, IConfig config) { if (benchmarkCase == null) { throw new ArgumentNullException(nameof(benchmarkCase)); } this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); this.diagnoser = diagnoser; IsDiagnoserAttached = diagnoser != null; Config = config; if (diagnoser != null) { diagnoserActionParameters = new DiagnoserActionParameters( Process.GetCurrentProcess(), benchmarkCase,
/// <summary>Creates a new instance of <see cref="InProcessHostApi"/>.</summary> /// <param name="benchmark">Current benchmark.</param> /// <param name="logger">Optional logger for informational output.</param> /// <param name="diagnoser">Diagnosers, if attached.</param> public InProcessHostApi( [NotNull] Benchmark benchmark, [CanBeNull] ILogger logger, [CanBeNull] IDiagnoser diagnoser) { if (benchmark == null) { throw new ArgumentNullException(nameof(benchmark)); } _benchmark = benchmark; _logger = logger; _diagnoser = diagnoser; IsDiagnoserAttached = diagnoser != null; if (diagnoser != null) { _currentProcess = Process.GetCurrentProcess(); } }
public SynchronousProcessOutputLoggerWithDiagnoser(ILogger logger, Process process, IDiagnoser diagnoser, BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, IConfig config) { if (!process.StartInfo.RedirectStandardOutput) { throw new NotSupportedException("set RedirectStandardOutput to true first"); } if (!process.StartInfo.RedirectStandardInput) { throw new NotSupportedException("set RedirectStandardInput to true first"); } this.logger = logger; this.process = process; this.diagnoser = diagnoser; diagnoserActionParameters = new DiagnoserActionParameters(process, benchmarkCase, benchmarkId, config); LinesWithResults = new List <string>(); LinesWithExtraOutput = new List <string>(); }
public SynchronousProcessOutputLoggerWithDiagnoser(ILogger logger, Process process, IDiagnoser diagnoser, BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, bool noAcknowledgments) { if (!process.StartInfo.RedirectStandardOutput) { throw new NotSupportedException("set RedirectStandardOutput to true first"); } if (!(process.StartInfo.RedirectStandardInput || benchmarkCase.GetRuntime() is WasmRuntime || noAcknowledgments)) { throw new NotSupportedException("set RedirectStandardInput to true first"); } this.logger = logger; this.process = process; this.diagnoser = diagnoser; diagnoserActionParameters = new DiagnoserActionParameters(process, benchmarkCase, benchmarkId); LinesWithResults = new List <string>(); LinesWithExtraOutput = new List <string>(); }
public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IDiagnoser compositeDiagnoser = null) { if (consoleHandler == null) { consoleHandler = new ConsoleHandler(logger); Console.CancelKeyPress += consoleHandler.EventHandler; } var exeName = Path.Combine(buildResult.DirectoryPath, "Program.exe"); var args = string.Empty; if (File.Exists(exeName)) { try { var startInfo = CreateStartInfo(benchmark, exeName, args); using (var process = Process.Start(startInfo)) { if (process != null) { if (compositeDiagnoser != null) compositeDiagnoser.ProcessStarted(process); consoleHandler.SetProcess(process); var result = ExecuteImpl(process, exeName, benchmark, logger, compositeDiagnoser); if (compositeDiagnoser != null) compositeDiagnoser.ProcessStopped(process); return result; } } } finally { consoleHandler?.ClearProcess(); } } return new ExecuteResult(false, new string[0]); }
/// <summary>Creates a new instance of <see cref="InProcessHost"/>.</summary> /// <param name="benchmark">Current benchmark.</param> /// <param name="logger">Logger for informational output.</param> /// <param name="diagnoser">Diagnosers, if attached.</param> public InProcessHost(Benchmark benchmark, ILogger logger, IDiagnoser diagnoser) { if (benchmark == null) { throw new ArgumentNullException(nameof(benchmark)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } this.benchmark = benchmark; this.logger = logger; this.diagnoser = diagnoser; IsDiagnoserAttached = diagnoser != null; if (diagnoser != null) { currentProcess = Process.GetCurrentProcess(); } }
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)); } }
private ExecuteResult Execute(Benchmark benchmark, ILogger logger, string exeName, string workingDirectory, string args, IDiagnoser diagnoser) { if (consoleHandler == null) { consoleHandler = new ConsoleHandler(logger); Console.CancelKeyPress += consoleHandler.EventHandler; } try { using (var process = new Process { StartInfo = CreateStartInfo(benchmark, exeName, args, workingDirectory) }) { var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmark); return Execute(process, benchmark, loggerWithDiagnoser, diagnoser, logger); } } finally { consoleHandler.ClearProcess(); } }
private ExecuteResult Execute(Process process, Benchmark benchmark, SynchronousProcessOutputLoggerWithDiagnoser loggerWithDiagnoser, IDiagnoser compositeDiagnoser, ILogger logger) { consoleHandler.SetProcess(process); process.Start(); process.EnsureHighPriority(logger); if (benchmark.Job.Env.HasValue(EnvMode.AffinityCharacteristic)) { process.EnsureProcessorAffinity(benchmark.Job.Env.Affinity); } loggerWithDiagnoser.ProcessInput(); process.WaitForExit(); // should we add timeout here? if (process.ExitCode == 0) { return new ExecuteResult(true, process.ExitCode, loggerWithDiagnoser.LinesWithResults, loggerWithDiagnoser.LinesWithExtraOutput); } return new ExecuteResult(true, process.ExitCode, new string[0], new string[0]); }
private ExecuteResult Execute(Process process, Benchmark benchmark, SynchronousProcessOutputLoggerWithDiagnoser loggerWithDiagnoser, IDiagnoser compositeDiagnoser, ILogger logger) { consoleHandler.SetProcess(process); process.Start(); process.EnsureHighPriority(logger); if (benchmark.Job.Env.HasValue(EnvMode.AffinityCharacteristic)) { process.EnsureProcessorAffinity(benchmark.Job.Env.Affinity); } loggerWithDiagnoser.ProcessInput(); process.WaitForExit(); // should we add timeout here? if (process.ExitCode == 0) { return(new ExecuteResult(true, process.ExitCode, loggerWithDiagnoser.LinesWithResults, loggerWithDiagnoser.LinesWithExtraOutput)); } return(new ExecuteResult(true, process.ExitCode, new string[0], new string[0])); }
private ExecuteResult Execute(Benchmark benchmark, ILogger logger, string exePath, string workingDirectory, string args, IDiagnoser diagnoser, IResolver resolver, IConfig config) { ConsoleHandler.EnsureInitialized(logger); try { using (var process = new Process { StartInfo = CreateStartInfo(benchmark, exePath, args, workingDirectory, resolver) }) { var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmark, config); return(Execute(process, benchmark, loggerWithDiagnoser, logger)); } } finally { ConsoleHandler.Instance.ClearProcess(); } }
private ExecuteResult Execute(Benchmark benchmark, ILogger logger, string exeName, string workingDirectory, string args, IDiagnoser diagnoser) { if (consoleHandler == null) { consoleHandler = new ConsoleHandler(logger); Console.CancelKeyPress += consoleHandler.EventHandler; } try { using (var process = new Process { StartInfo = CreateStartInfo(benchmark, exeName, args, workingDirectory) }) { var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmark); return(Execute(process, benchmark, loggerWithDiagnoser, diagnoser, logger)); } } finally { consoleHandler.ClearProcess(); } }
public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IDiagnoser compositeDiagnoser = null) { var exePath = buildResult.ExecutablePath; var args = string.Empty; if (!File.Exists(exePath)) { return(new ExecuteResult(false, new string[0])); } return(Execute(benchmark, logger, exePath, null, args, compositeDiagnoser)); }
public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IDiagnoser diagnoser) { logger.WriteLine("Executing"); Done = true; return(new ExecuteResult(true, new string[0])); }
public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser diagnoser) { logger.WriteLine("Executing"); Done = true; return new ExecuteResult(true, 0, new string[0], new string[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 ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser compositeDiagnoser = null) { var exePath = buildResult.ArtifactsPaths.ExecutablePath; var args = compositeDiagnoser == null ? string.Empty : Engine.Signals.DiagnoserIsAttachedParam; if (!File.Exists(exePath)) { return(new ExecuteResult(false, -1, Array.Empty <string>(), Array.Empty <string>())); } return(Execute(benchmark, logger, exePath, null, args, compositeDiagnoser, resolver)); }
private ExecuteResult Execute(BenchmarkCase benchmarkCase, BenchmarkId benchmarkId, ILogger logger, string exePath, string workingDirectory, string args, IDiagnoser diagnoser, IResolver resolver) { ConsoleExitHandler.Instance.Logger = logger; try { using (var process = new Process { StartInfo = CreateStartInfo(benchmarkCase, exePath, args, workingDirectory, resolver) }) { var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmarkCase, benchmarkId); diagnoser?.Handle(HostSignal.BeforeProcessStart, new DiagnoserActionParameters(process, benchmarkCase, benchmarkId)); return(Execute(process, benchmarkCase, loggerWithDiagnoser, logger)); } } finally { ConsoleExitHandler.Instance.Process = null; ConsoleExitHandler.Instance.Logger = null; diagnoser?.Handle(HostSignal.AfterProcessExit, new DiagnoserActionParameters(null, benchmarkCase, benchmarkId)); } }