config: save asynchronously to prevent hitches

This commit is contained in:
goat 2024-12-29 13:17:03 +01:00
parent 01980c3133
commit c79b1cd83a
3 changed files with 125 additions and 2 deletions

View file

@ -4,6 +4,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Dalamud.Game.Text;
using Dalamud.Interface;
@ -45,6 +46,8 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
[JsonIgnore]
private bool isSaveQueued;
private Task? writeTask;
/// <summary>
/// Delegate for the <see cref="DalamudConfiguration.DalamudConfigurationSaved"/> event that occurs when the dalamud configuration is saved.
/// </summary>
@ -560,6 +563,9 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
{
// Make sure that we save, if a save is queued while we are shutting down
this.Update();
// Wait for the write task to finish
this.writeTask?.Wait();
}
/// <summary>
@ -614,8 +620,22 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
if (this.configPath is null)
throw new InvalidOperationException("configPath is not set.");
Service<ReliableFileStorage>.Get().WriteAllText(
this.configPath, JsonConvert.SerializeObject(this, SerializerSettings));
// Wait for previous write to finish
this.writeTask?.Wait();
this.writeTask = Task.Run(() =>
{
Service<ReliableFileStorage>.Get().WriteAllText(
this.configPath,
JsonConvert.SerializeObject(this, SerializerSettings));
}).ContinueWith(t =>
{
if (t.IsFaulted)
{
Log.Error(t.Exception, "Failed to save DalamudConfiguration to {Path}", this.configPath);
}
});
this.DalamudConfigurationSaved?.Invoke(this);
}
}

View file

@ -60,6 +60,7 @@ internal class DataWindow : Window, IDisposable
new ToastWidget(),
new UiColorWidget(),
new UldWidget(),
new VfsWidget(),
};
private readonly IOrderedEnumerable<IDataWindowWidget> orderedModules;

View file

@ -0,0 +1,102 @@
using System.Diagnostics;
using System.IO;
using Dalamud.Configuration.Internal;
using Dalamud.Storage;
using ImGuiNET;
using Serilog;
namespace Dalamud.Interface.Internal.Windows.Data.Widgets;
/// <summary>
/// Widget for displaying configuration info.
/// </summary>
internal class VfsWidget : IDataWindowWidget
{
private int numBytes = 1024;
private int reps = 1;
/// <inheritdoc/>
public string[]? CommandShortcuts { get; init; } = { "vfs" };
/// <inheritdoc/>
public string DisplayName { get; init; } = "VFS Performance";
/// <inheritdoc/>
public bool Ready { get; set; }
/// <inheritdoc/>
public void Load()
{
this.Ready = true;
}
/// <inheritdoc/>
public void Draw()
{
var service = Service<ReliableFileStorage>.Get();
var dalamud = Service<Dalamud>.Get();
ImGui.InputInt("Num bytes", ref this.numBytes);
ImGui.InputInt("Reps", ref this.reps);
var path = Path.Combine(dalamud.StartInfo.WorkingDirectory!, "test.bin");
if (ImGui.Button("Write"))
{
Log.Information("=== WRITING ===");
var data = new byte[this.numBytes];
var stopwatch = new Stopwatch();
var acc = 0L;
for (var i = 0; i < this.reps; i++)
{
stopwatch.Restart();
service.WriteAllBytes(path, data);
stopwatch.Stop();
acc += stopwatch.ElapsedMilliseconds;
Log.Information("Turn {Turn} took {Ms}ms", i, stopwatch.ElapsedMilliseconds);
}
Log.Information("Took {Ms}ms in total", acc);
}
if (ImGui.Button("Read"))
{
Log.Information("=== READING ===");
var stopwatch = new Stopwatch();
var acc = 0L;
for (var i = 0; i < this.reps; i++)
{
stopwatch.Restart();
service.ReadAllBytes(path);
stopwatch.Stop();
acc += stopwatch.ElapsedMilliseconds;
Log.Information("Turn {Turn} took {Ms}ms", i, stopwatch.ElapsedMilliseconds);
}
Log.Information("Took {Ms}ms in total", acc);
}
if (ImGui.Button("Test Config"))
{
var config = Service<DalamudConfiguration>.Get();
Log.Information("=== READING ===");
var stopwatch = new Stopwatch();
var acc = 0L;
for (var i = 0; i < this.reps; i++)
{
stopwatch.Restart();
config.ForceSave();
stopwatch.Stop();
acc += stopwatch.ElapsedMilliseconds;
Log.Information("Turn {Turn} took {Ms}ms", i, stopwatch.ElapsedMilliseconds);
}
Log.Information("Took {Ms}ms in total", acc);
}
}
}