From ba8ce041cabfe27f3300170dfcf3b8864e2ee8ef Mon Sep 17 00:00:00 2001 From: ConfusedPolarBear <33811686+ConfusedPolarBear@users.noreply.github.com> Date: Tue, 17 May 2022 02:06:34 -0500 Subject: [PATCH] Limit parallelism & add mutex --- .../ScheduledTasks/FingerprinterTask.cs | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/FingerprinterTask.cs b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/FingerprinterTask.cs index 8a75883..bb125e2 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/FingerprinterTask.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/ScheduledTasks/FingerprinterTask.cs @@ -46,8 +46,16 @@ public class FingerprinterTask : IScheduledTask private readonly ILogger _logger; + /// + /// Lock which guards the fingerprint cache dictionary. + /// private readonly object _fingerprintCacheLock = new object(); + /// + /// Lock which guards the shared dictionary of intros. + /// + private readonly object _introsLock = new object(); + /// /// Temporary fingerprint cache to speed up reanalysis. /// Fingerprints are removed from this after a season is analyzed. @@ -95,7 +103,11 @@ public class FingerprinterTask : IScheduledTask var queue = Plugin.Instance!.AnalysisQueue; var totalProcessed = 0; - Parallel.ForEach(queue, (season) => + // TODO: make configurable + var options = new ParallelOptions(); + options.MaxDegreeOfParallelism = 2; + + Parallel.ForEach(queue, options, (season) => { var first = season.Value[0]; @@ -140,6 +152,8 @@ public class FingerprinterTask : IScheduledTask KeyValuePair> season, CancellationToken cancellationToken) { + var seasonIntros = new Dictionary(); + var first = season.Value[0]; /* Don't analyze specials or seasons with an insufficient number of episodes. @@ -206,8 +220,8 @@ public class FingerprinterTask : IScheduledTask var (lhsIntro, rhsIntro) = FingerprintEpisodes(lhs, rhs); - Plugin.Instance.Intros![lhsIntro.EpisodeId] = lhsIntro; - Plugin.Instance.Intros![rhsIntro.EpisodeId] = rhsIntro; + seasonIntros[lhsIntro.EpisodeId] = lhsIntro; + seasonIntros[rhsIntro.EpisodeId] = rhsIntro; if (!lhsIntro.Valid) { @@ -223,7 +237,16 @@ public class FingerprinterTask : IScheduledTask } } - Plugin.Instance!.SaveTimestamps(); + // Ensure only one thread at a time can update the shared intro dictionary. + lock (_introsLock) + { + foreach (var intro in seasonIntros) + { + Plugin.Instance!.Intros[intro.Key] = intro.Value; + } + + Plugin.Instance!.SaveTimestamps(); + } if (cancellationToken.IsCancellationRequested || !everFoundIntro) { @@ -603,7 +626,10 @@ public class FingerprinterTask : IScheduledTask oldDuration, newDuration); - Plugin.Instance!.Intros[episode.EpisodeId] = newRhs; + lock (_introsLock) + { + Plugin.Instance!.Intros[episode.EpisodeId] = newRhs; + } } }