From 9d4cb0a4ece294c9a9f57244662d95b4a0868d0c Mon Sep 17 00:00:00 2001 From: rlauuzo <46294892+rlauuzo@users.noreply.github.com> Date: Wed, 8 May 2024 16:27:16 +0200 Subject: [PATCH] Replace Dictionary + locks with ConcurrentDictionary (#143) --- .../Controllers/SkipIntroController.cs | 2 +- .../Controllers/VisualizationController.cs | 9 +- .../FFmpegWrapper.cs | 9 +- .../Plugin.cs | 122 +++++------------- .../QueueManager.cs | 2 +- 5 files changed, 41 insertions(+), 103 deletions(-) diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/Controllers/SkipIntroController.cs b/ConfusedPolarBear.Plugin.IntroSkipper/Controllers/SkipIntroController.cs index e373670..ae025ee 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/Controllers/SkipIntroController.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/Controllers/SkipIntroController.cs @@ -128,7 +128,7 @@ public class SkipIntroController : ControllerBase Plugin.Instance!.Credits.Clear(); } - Plugin.Instance!.SaveTimestamps(); + Plugin.Instance!.SaveTimestamps(mode); return NoContent(); } diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/Controllers/VisualizationController.cs b/ConfusedPolarBear.Plugin.IntroSkipper/Controllers/VisualizationController.cs index 0048c12..016c853 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/Controllers/VisualizationController.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/Controllers/VisualizationController.cs @@ -139,11 +139,12 @@ public class VisualizationController : ControllerBase foreach (var e in episodes) { - Plugin.Instance!.Intros.Remove(e.EpisodeId); - Plugin.Instance!.Credits.Remove(e.EpisodeId); + Plugin.Instance!.Intros.TryRemove(e.EpisodeId, out _); + Plugin.Instance!.Credits.TryRemove(e.EpisodeId, out _); } - Plugin.Instance!.SaveTimestamps(); + Plugin.Instance!.SaveTimestamps(AnalysisMode.Introduction); + Plugin.Instance!.SaveTimestamps(AnalysisMode.Credits); return NoContent(); } @@ -160,7 +161,7 @@ public class VisualizationController : ControllerBase { var tr = new TimeRange(timestamps.IntroStart, timestamps.IntroEnd); Plugin.Instance!.Intros[id] = new Intro(id, tr); - Plugin.Instance.SaveTimestamps(); + Plugin.Instance.SaveTimestamps(AnalysisMode.Introduction); return NoContent(); } diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/FFmpegWrapper.cs b/ConfusedPolarBear.Plugin.IntroSkipper/FFmpegWrapper.cs index 05e048b..1731db6 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/FFmpegWrapper.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/FFmpegWrapper.cs @@ -33,7 +33,7 @@ public static class FFmpegWrapper private static Dictionary ChromaprintLogs { get; set; } = new(); - private static ConcurrentDictionary>> InvertedIndexCache { get; set; } = new(); + private static ConcurrentDictionary<(Guid Id, AnalysisMode Mode), Dictionary> InvertedIndexCache { get; set; } = new(); /// /// Check that the installed version of ffmpeg supports chromaprint. @@ -140,10 +140,7 @@ public static class FFmpegWrapper /// Inverted index. public static Dictionary CreateInvertedIndex(Guid id, uint[] fingerprint, AnalysisMode mode) { - var innerDictionary = InvertedIndexCache.GetOrAdd(mode, _ => new ConcurrentDictionary>()); - - // Check if cached for the ID - if (innerDictionary.TryGetValue(id, out var cached)) + if (InvertedIndexCache.TryGetValue((id, mode), out var cached)) { return cached; } @@ -159,7 +156,7 @@ public static class FFmpegWrapper invIndex[point] = i; } - innerDictionary[id] = invIndex; + InvertedIndexCache[(id, mode)] = invIndex; return invIndex; } diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/Plugin.cs b/ConfusedPolarBear.Plugin.IntroSkipper/Plugin.cs index e4d83b6..07889f9 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/Plugin.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/Plugin.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; @@ -140,17 +141,17 @@ public class Plugin : BasePlugin, IHasWebPages /// /// Gets the results of fingerprinting all episodes. /// - public Dictionary Intros { get; } = new(); + public ConcurrentDictionary Intros { get; } = new(); /// /// Gets all discovered ending credits. /// - public Dictionary Credits { get; } = new(); + public ConcurrentDictionary Credits { get; } = new(); /// /// Gets the most recent media item queue. /// - public Dictionary> QueuedMediaItems { get; } = new(); + public ConcurrentDictionary> QueuedMediaItems { get; } = new(); /// /// Gets or sets the total number of episodes in the queue. @@ -183,91 +184,33 @@ public class Plugin : BasePlugin, IHasWebPages /// public static Plugin? Instance { get; private set; } - /// - /// Save timestamps to disk. - /// - public void SaveTimestamps() - { - lock (_serializationLock) - { - var introList = new List(); - - // Serialize intros - foreach (var intro in Instance!.Intros) - { - introList.Add(intro.Value); - } - - try - { - XmlSerializationHelper.SerializeToXml(introList, _introPath); - } - catch (Exception e) - { - _logger.LogError("SaveTimestamps intros {Message}", e.Message); - } - - // Serialize credits - introList.Clear(); - - foreach (var intro in Instance.Credits) - { - introList.Add(intro.Value); - } - - try - { - XmlSerializationHelper.SerializeToXml(introList, _creditsPath); - } - catch (Exception e) - { - _logger.LogError("SaveTimestamps credits {Message}", e.Message); - } - } - } - /// /// Save timestamps to disk. /// /// Mode. public void SaveTimestamps(AnalysisMode mode) { + List introList = new List(); + var filePath = mode == AnalysisMode.Introduction + ? _introPath + : _creditsPath; + + lock (_introsLock) + { + introList.AddRange(mode == AnalysisMode.Introduction + ? Instance!.Intros.Values + : Instance!.Credits.Values); + } + lock (_serializationLock) { - var introList = new List(); - - // Serialize intros - if (mode == AnalysisMode.Introduction) + try { - foreach (var intro in Instance!.Intros) - { - introList.Add(intro.Value); - } - - try - { - XmlSerializationHelper.SerializeToXml(introList, _introPath); - } - catch (Exception e) - { - _logger.LogError("SaveTimestamps intros {Message}", e.Message); - } + XmlSerializationHelper.SerializeToXml(introList, filePath); } - else if (mode == AnalysisMode.Credits) + catch (Exception e) { - foreach (var intro in Instance!.Credits) - { - introList.Add(intro.Value); - } - - try - { - XmlSerializationHelper.SerializeToXml(introList, _creditsPath); - } - catch (Exception e) - { - _logger.LogError("SaveTimestamps credits {Message}", e.Message); - } + _logger.LogError("SaveTimestamps {Message}", e.Message); } } } @@ -284,7 +227,7 @@ public class Plugin : BasePlugin, IHasWebPages foreach (var intro in introList) { - Instance!.Intros[intro.EpisodeId] = intro; + Instance!.Intros.TryAdd(intro.EpisodeId, intro); } } @@ -294,7 +237,7 @@ public class Plugin : BasePlugin, IHasWebPages foreach (var credit in creditList) { - Instance!.Credits[credit.EpisodeId] = credit; + Instance!.Credits.TryAdd(credit.EpisodeId, credit); } } } @@ -394,22 +337,19 @@ public class Plugin : BasePlugin, IHasWebPages internal void UpdateTimestamps(Dictionary newTimestamps, AnalysisMode mode) { - lock (_introsLock) + foreach (var intro in newTimestamps) { - foreach (var intro in newTimestamps) + if (mode == AnalysisMode.Introduction) { - if (mode == AnalysisMode.Introduction) - { - Instance!.Intros[intro.Key] = intro.Value; - } - else if (mode == AnalysisMode.Credits) - { - Instance!.Credits[intro.Key] = intro.Value; - } + Instance!.Intros.AddOrUpdate(intro.Key, intro.Value, (key, oldValue) => intro.Value); + } + else if (mode == AnalysisMode.Credits) + { + Instance!.Credits.AddOrUpdate(intro.Key, intro.Value, (key, oldValue) => intro.Value); } - - Instance!.SaveTimestamps(mode); } + + SaveTimestamps(mode); } /// diff --git a/ConfusedPolarBear.Plugin.IntroSkipper/QueueManager.cs b/ConfusedPolarBear.Plugin.IntroSkipper/QueueManager.cs index a407613..46a6b0a 100644 --- a/ConfusedPolarBear.Plugin.IntroSkipper/QueueManager.cs +++ b/ConfusedPolarBear.Plugin.IntroSkipper/QueueManager.cs @@ -84,7 +84,7 @@ public class QueueManager Plugin.Instance.QueuedMediaItems.Clear(); foreach (var kvp in _queuedEpisodes) { - Plugin.Instance.QueuedMediaItems[kvp.Key] = kvp.Value; + Plugin.Instance.QueuedMediaItems.TryAdd(kvp.Key, kvp.Value); } return new(_queuedEpisodes);