Browse Source

Config transaction objects now reued to minimize GC pressure

pull/46/head
Anairkoen Schno 4 years ago
parent
commit
f0fb1c0f83
1 changed files with 41 additions and 20 deletions
  1. +41
    -20
      IPA.Loader/Config/Stores/GeneratedStore.cs

+ 41
- 20
IPA.Loader/Config/Stores/GeneratedStore.cs View File

@ -126,6 +126,7 @@ namespace IPA.Config.Stores
{ {
private readonly IGeneratedStore generated; private readonly IGeneratedStore generated;
private bool inChangeTransaction = false; private bool inChangeTransaction = false;
private bool changedInTransaction = false;
internal static ConstructorInfo Ctor = typeof(Impl).GetConstructor(new[] { typeof(IGeneratedStore) }); internal static ConstructorInfo Ctor = typeof(Impl).GetConstructor(new[] { typeof(IGeneratedStore) });
public Impl(IGeneratedStore store) => generated = store; public Impl(IGeneratedStore store) => generated = store;
@ -173,41 +174,61 @@ namespace IPA.Config.Stores
internal static MethodInfo ImplChangeTransactionMethod = typeof(Impl).GetMethod(nameof(ImplChangeTransaction)); internal static MethodInfo ImplChangeTransactionMethod = typeof(Impl).GetMethod(nameof(ImplChangeTransaction));
public static IDisposable ImplChangeTransaction(IGeneratedStore s, IDisposable nest) => FindImpl(s).ChangeTransaction(nest); public static IDisposable ImplChangeTransaction(IGeneratedStore s, IDisposable nest) => FindImpl(s).ChangeTransaction(nest);
// TODO: use some fixed pool of these, because their lifetimes are hella short
// TODO: improve trasactionals so they don't always save in every case
public IDisposable ChangeTransaction(IDisposable nest, bool takeWrite = true) public IDisposable ChangeTransaction(IDisposable nest, bool takeWrite = true)
=> new ChangeTransactionObj(this, !inChangeTransaction, nest, takeWrite && !WriteSyncObject.IsWriteLockHeld);
=> GetFreeTransaction().InitWith(this, !inChangeTransaction, nest, takeWrite && !WriteSyncObject.IsWriteLockHeld);
private ChangeTransactionObj GetFreeTransaction()
=> freeTransactionObjs.Count > 0 ? freeTransactionObjs.Pop()
: new ChangeTransactionObj();
// TODO: maybe sometimes clean this?
private static readonly Stack<ChangeTransactionObj> freeTransactionObjs = new Stack<ChangeTransactionObj>();
private sealed class ChangeTransactionObj : IDisposable private sealed class ChangeTransactionObj : IDisposable
{ {
private readonly Impl impl;
private readonly bool owns;
private readonly bool ownsWrite;
private readonly IDisposable nested;
private struct Data
{
public readonly Impl impl;
public readonly bool owns;
public readonly bool ownsWrite;
public readonly IDisposable nested;
public ChangeTransactionObj(Impl impl, bool owning, IDisposable nest, bool takeWrite)
public Data(Impl impl, bool owning, bool takeWrite, IDisposable nest)
{
this.impl = impl; owns = owning; ownsWrite = takeWrite; nested = nest;
}
}
private Data data;
public ChangeTransactionObj InitWith(Impl impl, bool owning, IDisposable nest, bool takeWrite)
{ {
this.impl = impl;
nested = nest;
if (owns = owning)
data = new Data(impl, owning, takeWrite, nest);
if (data.owns)
impl.inChangeTransaction = true; impl.inChangeTransaction = true;
if (ownsWrite = takeWrite)
if (data.ownsWrite)
impl.TakeWrite(); impl.TakeWrite();
return this;
} }
public void Dispose()
public void Dispose() => Dispose(true);
private void Dispose(bool addToStore)
{ {
if (owns)
if (data.owns)
{ {
impl.inChangeTransaction = false;
impl.InvokeChanged();
data.impl.inChangeTransaction = false;
data.impl.InvokeChanged();
} }
nested?.Dispose();
if (ownsWrite)
impl.ReleaseWrite();
GC.SuppressFinalize(this);
data.nested?.Dispose();
if (data.ownsWrite)
data.impl.ReleaseWrite();
if (addToStore)
freeTransactionObjs.Push(this);
} }
~ChangeTransactionObj() => Dispose();
~ChangeTransactionObj() => Dispose(false);
} }
public static Impl FindImpl(IGeneratedStore store) public static Impl FindImpl(IGeneratedStore store)


Loading…
Cancel
Save