Skip to content

Commit

Permalink
config: save asynchronously to prevent hitches
Browse files Browse the repository at this point in the history
  • Loading branch information
goaaats committed Dec 29, 2024
1 parent 01980c3 commit c79b1cd
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 2 deletions.
24 changes: 22 additions & 2 deletions Dalamud/Configuration/Internal/DalamudConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

using Dalamud.Game.Text;
using Dalamud.Interface;
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -560,6 +563,9 @@ void IInternalDisposableService.DisposeService()
{
// 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>
Expand Down Expand Up @@ -614,8 +620,22 @@ private void Save()
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);
}
}
1 change: 1 addition & 0 deletions Dalamud/Interface/Internal/Windows/Data/DataWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ internal class DataWindow : Window, IDisposable
new ToastWidget(),
new UiColorWidget(),
new UldWidget(),
new VfsWidget(),
};

private readonly IOrderedEnumerable<IDataWindowWidget> orderedModules;
Expand Down
102 changes: 102 additions & 0 deletions Dalamud/Interface/Internal/Windows/Data/Widgets/VfsWidget.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}

0 comments on commit c79b1cd

Please sign in to comment.