private static void Warmup(ImmutableArray <SourceFile> files) { Console.WriteLine("Warming up..."); var addLock = new object(); var reportLock = new object(); var warmups = new SegmentedList <double>(1 << (int)Math.Ceiling(Math.Log2(files.Length * s_warmupCount))); var nextReport = -1L; var parsed = 0; var total = files.Length * s_warmupCount; var start = Stopwatch.GetTimestamp(); Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = s_threadsCount }, (file, _s, idx) => { for (var round = 0; round < s_warmupCount; round++) { var tStart = Stopwatch.GetTimestamp(); _ = LuaSyntaxTree.ParseText(file.Text, path: file.FileName); var tEnd = Stopwatch.GetTimestamp(); lock (addLock) warmups.Add(tEnd - tStart); var ourParsed = Interlocked.Increment(ref parsed); if (nextReport <= Stopwatch.GetTimestamp() && Monitor.TryEnter(reportLock)) { try { var delta = Stopwatch.GetTimestamp() - start; var timePerItem = (double)delta / ourParsed; var remaining = total - ourParsed; var eta = (long)Math.Ceiling(remaining * timePerItem); Console.WriteLine($"Warmup progress: {ourParsed}/{total}. ETA: {TimeSpan.FromTicks(eta)}"); nextReport = Stopwatch.GetTimestamp() + s_reportInterval; } finally { Monitor.Exit(reportLock); } } } }); var statistics = new Statistics(warmups.Take(files.Length * s_warmupCount)); using var writer = new IndentedTextWriter(Console.Out); writer.WriteLine($"Warmup results:"); PrintStatistics(writer, statistics, static d => Duration.Format(ceil(d)));