Skip to content

Commit bad88cd

Browse files
committed
ModList Caching - ModList data is now cached and checked vs file modified time, rather than JSON Decoding the entire file every access.
1 parent 65b46b2 commit bad88cd

File tree

1 file changed

+68
-1
lines changed

1 file changed

+68
-1
lines changed

xivModdingFramework/Mods/Modding.cs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using System.Collections.Generic;
2121
using System.IO;
2222
using System.Linq;
23+
using System.Threading;
2324
using System.Threading.Tasks;
2425
using xivModdingFramework.General.Enums;
2526
using xivModdingFramework.Helpers;
@@ -37,6 +38,7 @@ public class Modding
3738
{
3839
private readonly DirectoryInfo _gameDirectory;
3940
private readonly Version _modlistVersion = new Version(1, 0);
41+
private static SemaphoreSlim _modlistSemaphore = new SemaphoreSlim(1);
4042

4143
public DirectoryInfo ModListDirectory { get; }
4244

@@ -52,14 +54,79 @@ public Modding(DirectoryInfo gameDirectory)
5254

5355
}
5456

57+
// Caching information for modlists.
58+
private static Dictionary<string, DateTime> _cachedModlistsModTime = new Dictionary<string, DateTime>();
59+
private static Dictionary<string, ModList> _cachedModlists = new Dictionary<string, ModList>();
5560
public ModList GetModList()
5661
{
57-
return JsonConvert.DeserializeObject<ModList>(File.ReadAllText(ModListDirectory.FullName));
62+
ModList val;
63+
_modlistSemaphore.Wait();
64+
try
65+
{
66+
var modTime = File.GetLastWriteTime(ModListDirectory.FullName);
67+
if (_cachedModlists.ContainsKey(ModListDirectory.FullName) && modTime <= _cachedModlistsModTime[ModListDirectory.FullName])
68+
{
69+
// We have a cached file, and the modList file has not been touched since we cached it.
70+
// Return the cached copy (Skip full read & Json deserialize)
71+
val = _cachedModlists[ModListDirectory.FullName];
72+
}
73+
else
74+
{
75+
// Cache was either stale or missing, load the file from disk and update cache.
76+
val = JsonConvert.DeserializeObject<ModList>(File.ReadAllText(ModListDirectory.FullName));
77+
modTime = File.GetLastWriteTime(ModListDirectory.FullName);
78+
79+
_cachedModlists[ModListDirectory.FullName] = val;
80+
_cachedModlistsModTime[ModListDirectory.FullName] = modTime;
81+
82+
}
83+
} finally {
84+
_modlistSemaphore.Release();
85+
}
86+
return val;
87+
}
88+
public async Task<ModList> GetModListAsync()
89+
{
90+
ModList val;
91+
await _modlistSemaphore.WaitAsync();
92+
try
93+
{
94+
var modTime = File.GetLastWriteTime(ModListDirectory.FullName);
95+
if (_cachedModlists.ContainsKey(ModListDirectory.FullName) && modTime <= _cachedModlistsModTime[ModListDirectory.FullName])
96+
{
97+
// We have a cached file, and the modList file has not been touched since we cached it.
98+
// Return the cached copy (Skip full read & Json deserialize)
99+
val = _cachedModlists[ModListDirectory.FullName];
100+
}
101+
else
102+
{
103+
// Cache was either stale or missing, load the file from disk and update cache.
104+
val = JsonConvert.DeserializeObject<ModList>(File.ReadAllText(ModListDirectory.FullName));
105+
modTime = File.GetLastWriteTime(ModListDirectory.FullName);
106+
107+
_cachedModlists[ModListDirectory.FullName] = val;
108+
_cachedModlistsModTime[ModListDirectory.FullName] = modTime;
109+
110+
}
111+
}
112+
finally
113+
{
114+
_modlistSemaphore.Release();
115+
}
116+
return val;
58117
}
59118

60119
public void SaveModList(ModList ml)
61120
{
121+
_modlistSemaphore.Wait();
122+
File.WriteAllText(ModListDirectory.FullName, JsonConvert.SerializeObject(ml, Formatting.Indented));
123+
_modlistSemaphore.Release();
124+
}
125+
public void SaveModListAsync(ModList ml)
126+
{
127+
_modlistSemaphore.WaitAsync();
62128
File.WriteAllText(ModListDirectory.FullName, JsonConvert.SerializeObject(ml, Formatting.Indented));
129+
_modlistSemaphore.Release();
63130
}
64131

65132
public async Task DeleteAllFilesAddedByTexTools()

0 commit comments

Comments
 (0)