Skip to content

Commit

Permalink
Add a change list to optimize datacache commit (neo-project#1619)
Browse files Browse the repository at this point in the history
  • Loading branch information
Qiao-Jin authored and Tommo-L committed Jun 22, 2020
1 parent bc1fcd3 commit 4050822
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 47 deletions.
26 changes: 15 additions & 11 deletions src/neo/IO/Caching/DataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class Trackable
}

private readonly Dictionary<TKey, Trackable> dictionary = new Dictionary<TKey, Trackable>();
private readonly HashSet<TKey> changeSet = new HashSet<TKey>();

public TValue this[TKey key]
{
Expand Down Expand Up @@ -65,6 +66,7 @@ public void Add(TKey key, TValue value)
Item = value,
State = trackable == null ? TrackState.Added : TrackState.Changed
};
changeSet.Add(key);
}
}

Expand Down Expand Up @@ -96,6 +98,7 @@ public void Commit()
{
dictionary.Remove(key);
}
changeSet.Clear();
}

public DataCache<TKey, TValue> CreateSnapshot()
Expand All @@ -114,9 +117,15 @@ public void Delete(TKey key)
if (dictionary.TryGetValue(key, out Trackable trackable))
{
if (trackable.State == TrackState.Added)
{
dictionary.Remove(key);
changeSet.Remove(key);
}
else
{
trackable.State = TrackState.Deleted;
changeSet.Add(key);
}
}
else
{
Expand All @@ -128,21 +137,13 @@ public void Delete(TKey key)
Item = item,
State = TrackState.Deleted
});
changeSet.Add(key);
}
}
}

protected abstract void DeleteInternal(TKey key);

public void DeleteWhere(Func<TKey, TValue, bool> predicate)
{
lock (dictionary)
{
foreach (Trackable trackable in dictionary.Where(p => p.Value.State != TrackState.Deleted && predicate(p.Key, p.Value.Item)).Select(p => p.Value))
trackable.State = TrackState.Deleted;
}
}

/// <summary>
/// Find the entries that start with the `key_prefix`
/// </summary>
Expand Down Expand Up @@ -204,8 +205,8 @@ public IEnumerable<Trackable> GetChangeSet()
{
lock (dictionary)
{
foreach (Trackable trackable in dictionary.Values.Where(p => p.State != TrackState.None))
yield return trackable;
foreach (TKey key in changeSet)
yield return dictionary[key];
}
}

Expand Down Expand Up @@ -234,6 +235,7 @@ public TValue GetAndChange(TKey key, Func<TValue> factory = null)
else if (trackable.State == TrackState.None)
{
trackable.State = TrackState.Changed;
changeSet.Add(key);
}
}
else
Expand All @@ -254,6 +256,7 @@ public TValue GetAndChange(TKey key, Func<TValue> factory = null)
trackable.State = TrackState.Changed;
}
dictionary.Add(key, trackable);
changeSet.Add(key);
}
return trackable.Item;
}
Expand Down Expand Up @@ -282,6 +285,7 @@ public TValue GetOrAdd(TKey key, Func<TValue> factory)
{
trackable.Item = factory();
trackable.State = TrackState.Added;
changeSet.Add(key);
}
else
{
Expand Down
17 changes: 0 additions & 17 deletions tests/neo.UnitTests/IO/Caching/UT_DataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,23 +246,6 @@ public void TestDelete()
myDataCache.InnerDict.ContainsKey(new MyKey("key2")).Should().BeFalse();
}

[TestMethod]
public void TestDeleteWhere()
{
myDataCache.Add(new MyKey("key1"), new MyValue("value1"));
myDataCache.Add(new MyKey("key2"), new MyValue("value2"));

myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4"));

myDataCache.DeleteWhere((k, v) => k.Key.StartsWith("key"));
myDataCache.Commit();
myDataCache.TryGet(new MyKey("key1")).Should().BeNull();
myDataCache.TryGet(new MyKey("key2")).Should().BeNull();
myDataCache.InnerDict.ContainsKey(new MyKey("key1")).Should().BeFalse();
myDataCache.InnerDict.ContainsKey(new MyKey("key2")).Should().BeFalse();
}

[TestMethod]
public void TestFind()
{
Expand Down
8 changes: 4 additions & 4 deletions tests/neo.UnitTests/SmartContract/UT_Syscalls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ public void System_Runtime_GasLeft()
public void System_Runtime_GetInvocationCounter()
{
ContractState contractA, contractB, contractC;
var snapshot = Blockchain.Singleton.GetSnapshot();
var snapshot = Blockchain.Singleton.GetSnapshot().Clone();
var contracts = snapshot.Contracts;

// Create dummy contracts
Expand All @@ -339,9 +339,9 @@ public void System_Runtime_GetInvocationCounter()
// Init A,B,C contracts
// First two drops is for drop method and arguments

contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractA.ScriptHash.ToArray()));
contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractB.ScriptHash.ToArray()));
contracts.DeleteWhere((a, b) => a.ToArray().SequenceEqual(contractC.ScriptHash.ToArray()));
contracts.Delete(contractA.ScriptHash);
contracts.Delete(contractB.ScriptHash);
contracts.Delete(contractC.ScriptHash);
contractA.Manifest = TestUtils.CreateDefaultManifest(contractA.ScriptHash, "dummyMain");
contractB.Manifest = TestUtils.CreateDefaultManifest(contractA.ScriptHash, "dummyMain");
contractC.Manifest = TestUtils.CreateDefaultManifest(contractA.ScriptHash, "dummyMain");
Expand Down
18 changes: 3 additions & 15 deletions tests/neo.UnitTests/UT_DataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ public void TestSetup()
public void TestCachedFind_Between()
{
var snapshot = Blockchain.Singleton.GetSnapshot();
var storages = snapshot.Storages;
var storages = snapshot.Storages.CreateSnapshot();
var cache = new CloneCache<StorageKey, StorageItem>(storages);

storages.DeleteWhere((k, v) => k.Id == 0);

storages.Add
(
new StorageKey() { Key = new byte[] { 0x01, 0x01 }, Id = 0 },
Expand Down Expand Up @@ -53,19 +51,15 @@ public void TestCachedFind_Between()
cache.Find(new byte[5]).Select(u => u.Key.Key[1]).ToArray(),
new byte[] { 0x01, 0x02, 0x03 }
);

storages.DeleteWhere((k, v) => k.Id == 0);
}

[TestMethod]
public void TestCachedFind_Last()
{
var snapshot = Blockchain.Singleton.GetSnapshot();
var storages = snapshot.Storages;
var storages = snapshot.Storages.CreateSnapshot();
var cache = new CloneCache<StorageKey, StorageItem>(storages);

storages.DeleteWhere((k, v) => k.Id == 0);

storages.Add
(
new StorageKey() { Key = new byte[] { 0x00, 0x01 }, Id = 0 },
Expand All @@ -89,19 +83,15 @@ public void TestCachedFind_Last()
CollectionAssert.AreEqual(cache.Find(new byte[5]).Select(u => u.Key.Key[1]).ToArray(),
new byte[] { 0x01, 0x02 }
);

storages.DeleteWhere((k, v) => k.Id == 0);
}

[TestMethod]
public void TestCachedFind_Empty()
{
var snapshot = Blockchain.Singleton.GetSnapshot();
var storages = snapshot.Storages;
var storages = snapshot.Storages.CreateSnapshot();
var cache = new CloneCache<StorageKey, StorageItem>(storages);

storages.DeleteWhere((k, v) => k.Id == 0);

cache.Add
(
new StorageKey() { Key = new byte[] { 0x00, 0x02 }, Id = 0 },
Expand All @@ -117,8 +107,6 @@ public void TestCachedFind_Empty()
cache.Find(new byte[5]).Select(u => u.Key.Key[1]).ToArray(),
new byte[] { 0x02 }
);

storages.DeleteWhere((k, v) => k.Id == 0);
}
}
}

0 comments on commit 4050822

Please sign in to comment.