static IEnumerable <Checkpoint> EnumCheckpoints( ITextAccessIterator tai, PlainTextMatcher matcher, ProgressAndCancellation progressAndCancellation, LJTraceSource trace) { var advanceTime = new Stopwatch(); long advancesCount = 0; var matchingTime = new Stopwatch(); long matchCount = 0; for (;;) { StringSlice buf = new StringSlice(tai.CurrentBuffer); for (int startIdx = 0; ;) { matchingTime.Start(); var match = matcher.Match(buf, startIdx); matchingTime.Stop(); ++matchCount; if (!match.HasValue) { break; } yield return(new Checkpoint() { Position = tai.CharIndexToPosition(match.Value.MatchBegin), EndPosition = tai.CharIndexToPosition(match.Value.MatchEnd), IsMatch = true }); startIdx = match.Value.MatchEnd; progressAndCancellation.CheckTextIterationCancellation(); } advanceTime.Start(); bool stop = !tai.Advance(Math.Max(0, tai.CurrentBuffer.Length - matcher.MaxMatchLength)); advanceTime.Stop(); ++advancesCount; if (stop) { break; } yield return(new Checkpoint() { EndPosition = tai.CharIndexToPosition(0), IsMatch = false }); progressAndCancellation.CheckTextIterationCancellation(); } trace.Info("Stats: text buffer matching time: {0} ({1} times)", matchingTime.Elapsed, matchCount); trace.Info("Stats: text buffer advance time: {0}/{1}={2}", advanceTime.Elapsed, advancesCount, TimeSpan.FromTicks(advanceTime.ElapsedTicks / Math.Max(1, advancesCount))); }