Browse Source

Optimizations.
Calculating song dir write times only once or if the custom song dir mod
time changes.
Not remapping score saber data every time sorting changes.

Stephen Damm 6 years ago
parent
commit
1d83982915

+ 9 - 9
SongBrowserPlugin/DataAccess/ScoreSaberDatabase.cs

@@ -45,13 +45,13 @@ namespace SongBrowserPlugin.DataAccess
     {
         private Logger _log = new Logger("ScoreSaberDataFile");
 
-        public Dictionary<String, ScoreSaberData> SongNameToPp;
-        public Dictionary<String, ScoreSaberData> SongVersionToPp;
+        public Dictionary<String, ScoreSaberData> SongNameToScoreSaberData;
+        public Dictionary<String, ScoreSaberData> SongVersionToScoreSaberData;
 
         public ScoreSaberDataFile(byte[] data)
         {
-            SongNameToPp = new Dictionary<string, ScoreSaberData>();
-            SongVersionToPp = new Dictionary<string, ScoreSaberData>();
+            SongNameToScoreSaberData = new Dictionary<string, ScoreSaberData>();
+            SongVersionToScoreSaberData = new Dictionary<string, ScoreSaberData>();
 
             string result = System.Text.Encoding.UTF8.GetString(data);
             string[] lines = result.Split('\n');
@@ -89,22 +89,22 @@ namespace SongBrowserPlugin.DataAccess
                 string version = m.Groups["version"].Value;
 
                 ScoreSaberData ppData = null;
-                if (!SongVersionToPp.ContainsKey(version))
+                if (!SongVersionToScoreSaberData.ContainsKey(version))
                 {
                     ppData = new ScoreSaberData();
                     ppData.version = version;
                     ppData.name = name;
 
-                    SongVersionToPp.Add(version, ppData);
+                    SongVersionToScoreSaberData.Add(version, ppData);
                 }
                 else
                 {
-                    ppData = SongVersionToPp[version];
+                    ppData = SongVersionToScoreSaberData[version];
                 }
 
-                if (!SongNameToPp.ContainsKey(name))
+                if (!SongNameToScoreSaberData.ContainsKey(name))
                 {
-                    SongNameToPp.Add(name, ppData);
+                    SongNameToScoreSaberData.Add(name, ppData);
                 }
 
                 // add difficulty  

+ 47 - 24
SongBrowserPlugin/DataAccess/SongBrowserModel.cs

@@ -25,13 +25,14 @@ namespace SongBrowserPlugin
         private SongBrowserSettings _settings;
 
         // song list management
+        private double _customSongDirLastWriteTime = 0;
         private List<StandardLevelSO> _filteredSongs;
         private List<StandardLevelSO> _sortedSongs;
         private List<StandardLevelSO> _originalSongs;
         private Dictionary<String, SongLoaderPlugin.OverrideClasses.CustomLevel> _levelIdToCustomLevel;
         private Dictionary<String, double> _cachedLastWriteTimes;
         private Dictionary<string, int> _weights;
-        private Dictionary<string, ScoreSaberData> _ppMapping = null;
+        private Dictionary<string, ScoreSaberData> _levelIdToScoreSaberData = null;
         private Dictionary<String, DirectoryNode> _directoryTree;
         private Stack<DirectoryNode> _directoryStack = new Stack<DirectoryNode>();
 
@@ -77,11 +78,11 @@ namespace SongBrowserPlugin
             }
         }
 
-        public Dictionary<string, ScoreSaberData> PpMapping
+        public Dictionary<string, ScoreSaberData> LevelIdToScoreSaberData
         {
             get
             {
-                return _ppMapping;
+                return _levelIdToScoreSaberData;
             }
         }
 
@@ -161,6 +162,7 @@ namespace SongBrowserPlugin
         public SongBrowserModel()
         {
             _cachedLastWriteTimes = new Dictionary<String, double>();
+            _levelIdToScoreSaberData = new Dictionary<string, ScoreSaberData>();
 
             // Weights used for keeping the original songs in order
             // Invert the weights from the game so we can order by descending and make LINQ work with us...
@@ -224,19 +226,34 @@ namespace SongBrowserPlugin
 
             String customSongsPath = Path.Combine(Environment.CurrentDirectory, CUSTOM_SONGS_DIR);
             String cachedSongsPath = Path.Combine(customSongsPath, ".cache");
-            DateTime currentLastWriteTIme = File.GetLastWriteTimeUtc(customSongsPath);
+            double currentCustomSongDirLastWriteTIme = (File.GetLastWriteTimeUtc(customSongsPath) - EPOCH).TotalMilliseconds;
+            bool customSongDirChanged = false;
+            if (_customSongDirLastWriteTime != currentCustomSongDirLastWriteTIme)
+            {
+                customSongDirChanged = true;
+                _customSongDirLastWriteTime = currentCustomSongDirLastWriteTIme;
+            }
+
+            // This operation scales well
             IEnumerable<string> directories = Directory.EnumerateDirectories(customSongsPath, "*.*", SearchOption.AllDirectories);
 
-            // Get LastWriteTimes            
+            // Get LastWriteTimes   
+            Stopwatch lastWriteTimer = new Stopwatch();
+            lastWriteTimer.Start();
             foreach (var level in SongLoader.CustomLevels)
             {
-                //_log.Debug("Fetching LastWriteTime for {0}", slashed_dir);
-                _cachedLastWriteTimes[level.levelID] = (File.GetLastWriteTimeUtc(level.customSongInfo.path) - EPOCH).TotalMilliseconds;
+                // If we already know this levelID, don't both updating it.
+                if (!_cachedLastWriteTimes.ContainsKey(level.levelID) || customSongDirChanged)
+                {
+                    _cachedLastWriteTimes[level.levelID] = (File.GetLastWriteTimeUtc(level.customSongInfo.path) - EPOCH).TotalMilliseconds;
+                }
             }
+            lastWriteTimer.Stop();
+            _log.Info("Determining song download time took {0}ms", lastWriteTimer.ElapsedMilliseconds);
 
             // Update song Infos, directory tree, and sort
             this.UpdateSongInfos(_currentGamePlayMode);
-            this.UpdatePpMappings();
+            this.UpdateScoreSaberDataMapping();
             this.UpdateDirectoryTree(customSongsPath);
             this.ProcessSongList();
 
@@ -267,7 +284,9 @@ namespace SongBrowserPlugin
             foreach (var level in SongLoader.CustomLevels)
             {
                 if (!_levelIdToCustomLevel.Keys.Contains(level.levelID))
+                {
                     _levelIdToCustomLevel.Add(level.levelID, level);
+                }
             }
 
             _log.Debug("Song Browser knows about {0} songs from SongLoader...", _originalSongs.Count);
@@ -276,48 +295,52 @@ namespace SongBrowserPlugin
         /// <summary>
         /// Parse the current pp data file.
         /// </summary>
-        private void UpdatePpMappings()
+        private void UpdateScoreSaberDataMapping()
         {
-            _log.Trace("UpdatePpMappings()");
-
-            ScoreSaberDataFile ppDataFile = ScoreSaberDatabaseDownloader.Instance.ScoreSaberDataFile;
+            _log.Trace("UpdateScoreSaberDataMapping()");
 
-            _ppMapping = new Dictionary<string, ScoreSaberData>();
+            ScoreSaberDataFile scoreSaberDataFile = ScoreSaberDatabaseDownloader.Instance.ScoreSaberDataFile;
 
             // bail
-            if (ppDataFile == null)
+            if (scoreSaberDataFile == null)
             {
                 _log.Warning("Cannot fetch song difficulty data tsv file from DuoVR");
                 return;
             }
 
+            Regex versionRegex = new Regex(@".*/(?<version>[0-9]*-[0-9]*)/");
             foreach (var level in SongLoader.CustomLevels)
             {
-                ScoreSaberData ppData = null;
+                // Skip
+                if (_levelIdToScoreSaberData.ContainsKey(level.levelID))
+                {
+                    continue;
+                }
 
-                Regex versionRegex = new Regex(@".*/(?<version>[0-9]*-[0-9]*)/");
+                ScoreSaberData scoreSaberData = null;
+                
                 Match m = versionRegex.Match(level.customSongInfo.path);
                 if (m.Success)
                 {
                     String version = m.Groups["version"].Value;
-                    if (ppDataFile.SongVersionToPp.ContainsKey(version))
+                    if (scoreSaberDataFile.SongVersionToScoreSaberData.ContainsKey(version))
                     {
-                        ppData = ppDataFile.SongVersionToPp[version];
+                        scoreSaberData = scoreSaberDataFile.SongVersionToScoreSaberData[version];
                     }
                 }
 
-                if (ppData == null)
+                if (scoreSaberData == null)
                 {
-                    if (ppDataFile.SongVersionToPp.ContainsKey(level.songName))
+                    if (scoreSaberDataFile.SongVersionToScoreSaberData.ContainsKey(level.songName))
                     {
-                        ppData = ppDataFile.SongVersionToPp[level.songName];
+                        scoreSaberData = scoreSaberDataFile.SongVersionToScoreSaberData[level.songName];
                     }
                 }
 
-                if (ppData != null)
+                if (scoreSaberData != null)
                 {
                     //_log.Debug("{0} = {1}pp", level.songName, pp);
-                    _ppMapping.Add(level.levelID, ppData);
+                    _levelIdToScoreSaberData.Add(level.levelID, scoreSaberData);
                 }
             }            
         }
@@ -709,7 +732,7 @@ namespace SongBrowserPlugin
             _log.Info("Sorting song list by performance points...");
 
             _sortedSongs = levels
-                .OrderByDescending(x => _ppMapping.ContainsKey(x.levelID) ? _ppMapping[x.levelID].maxPp : 0)
+                .OrderByDescending(x => _levelIdToScoreSaberData.ContainsKey(x.levelID) ? _levelIdToScoreSaberData[x.levelID].maxPp : 0)
                 .ToList();
         }
 

+ 3 - 3
SongBrowserPlugin/UI/Browser/SongBrowserUI.cs

@@ -497,7 +497,7 @@ namespace SongBrowserPlugin.UI
             _playButton.gameObject.SetActive(true);
 
             // display pp potentially
-            if (this._model.PpMapping != null && this._levelDifficultyViewController.selectedDifficultyLevel != null)
+            if (this._model.LevelIdToScoreSaberData != null && this._levelDifficultyViewController.selectedDifficultyLevel != null)
             {
                 if (this._ppText == null)
                 {
@@ -525,10 +525,10 @@ namespace SongBrowserPlugin.UI
                 string difficultyString = difficulty.ToString();
 
                 _log.Debug("Checking if have info for song {0}", level.songName);
-                if (this._model.PpMapping.ContainsKey(level.levelID))
+                if (this._model.LevelIdToScoreSaberData.ContainsKey(level.levelID))
                 {
                     _log.Debug("Checking if have difficulty for song {0} difficulty {1}", level.songName, difficultyString);
-                    ScoreSaberData ppData = this._model.PpMapping[level.levelID];
+                    ScoreSaberData ppData = this._model.LevelIdToScoreSaberData[level.levelID];
                     if (ppData.difficultyToSaberDifficulty.ContainsKey(difficultyString))
                     {
                         _log.Debug("Display pp for song.");