Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added StoreCache #3701

Closed
110 changes: 110 additions & 0 deletions benchmarks/Neo.Benchmarks/Collections/Caching/Benchmarks.StoreCache.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright (C) 2015-2025 The Neo Project.
//
// Benchmarks.StoreCache.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using BenchmarkDotNet.Attributes;
using Neo.Collections.Caching;
using Neo.Persistence;
using Neo.SmartContract;
using System.Diagnostics;

namespace Neo.Benchmark.Collections.Caching
{
[MemoryDiagnoser] // Enabling Memory Diagnostics
[CsvMeasurementsExporter] // Export results in CSV format
[MarkdownExporter] // Exporting results in Markdown format
public class Benchmarks_StoreCache
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the benchmarks are not the same but changing the interface? it looks like the methods are totally different

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods do the same thing. However, StoreCache class is a collection, so you can convert StoreCache to any collection you want. This is how DataCache and other classes in neo should of been developed.

StoreCache inherits from

ICollection<KeyValuePair<TKey, TValue>>
IEnumerable<KeyValuePair<TKey, TValue>>
IEnumerable
IDictionary<TKey, TValue>
IReadOnlyCollection<KeyValuePair<TKey, TValue>>
IReadOnlyDictionary<TKey, TValue>
ICollection
IDictionary

{
private static readonly MemoryStore s_memoryStore = new();
private static readonly StoreCache<StorageKey, StorageItem> s_storeCache = new(s_memoryStore);
private static readonly DataCache s_dataCache = new SnapshotCache(s_memoryStore);

private static byte[] s_data = [];
private static StorageKey s_key;
private static StorageItem s_value;

[GlobalSetup]
public void Setup()
{
if (s_data.Length == 0)
{
s_data = new byte[4096];
Random.Shared.NextBytes(s_data);
s_key = new StorageKey(s_data);
s_value = new StorageItem(s_data);
}
}

[Benchmark]
public void TestStoreCacheAddAndUpdate()
{
s_storeCache.Add(s_key, s_value);
s_storeCache[s_key] = new(s_data);
}

[Benchmark]
public void TestStoreCacheRemove()
{
s_storeCache.Add(s_key, s_value);
Debug.Assert(s_storeCache.Remove(s_key, out _));
}

[Benchmark]
public void TestStoreCacheGetAlreadyCachedData()
{
s_storeCache.Add(s_key, s_value);
Debug.Assert(s_storeCache.TryGetValue(s_key, out _));
Debug.Assert(s_storeCache.ContainsKey(s_key));
_ = s_storeCache[s_key];
}

[Benchmark]
public void TestStoreCacheGetNonCachedData()
{
s_memoryStore.Put(s_key.ToArray(), s_key.ToArray());
Debug.Assert(s_storeCache.TryGetValue(s_key, out _));
Debug.Assert(s_storeCache.ContainsKey(s_key));
_ = s_storeCache[s_key];
}

[Benchmark]
public void TestDataCacheAddAndUpdate()
{
_ = s_dataCache.GetOrAdd(s_key, () => s_value);
_ = s_dataCache.GetAndChange(s_key, () => new(s_data));
}


[Benchmark]
public void TestDataCacheRemove()
{
_ = s_dataCache.GetOrAdd(s_key, () => s_value);
s_dataCache.Delete(s_key);
}

[Benchmark]
public void TestDataCacheGetAlreadyCachedData()
{
_ = s_dataCache.GetOrAdd(s_key, () => s_value);
_ = s_dataCache.GetAndChange(s_key);
Debug.Assert(s_dataCache.Contains(s_key));
_ = s_dataCache[s_key];
}

[Benchmark]
public void TestDataCacheGetNonCachedData()
{
s_memoryStore.Put(s_key.ToArray(), s_key.ToArray());
_ = s_dataCache.GetAndChange(s_key);
Debug.Assert(s_dataCache.Contains(s_key));
_ = s_dataCache[s_key];
}
}
}
15 changes: 7 additions & 8 deletions benchmarks/Neo.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@
// modifications are permitted.

using BenchmarkDotNet.Running;
using Neo.Benchmark;
using Neo.Benchmarks.Persistence.Benchmarks;
using Neo.SmartContract.Benchmark;
using Neo.Benchmark.Collections.Caching;

// BenchmarkRunner.Run<Benchmarks_PoCs>();
BenchmarkRunner.Run<Benchmarks_UInt160>();
BenchmarkRunner.Run<Benchmarks_Hash>();
BenchmarkRunner.Run<Benchmarks_StorageKey>();
BenchmarkRunner.Run<Bechmarks_ReadOnlyStoreView>();
BenchmarkRunner.Run<Bechmarks_LevelDB>();
//BenchmarkRunner.Run<Benchmarks_UInt160>();
//BenchmarkRunner.Run<Benchmarks_Hash>();
//BenchmarkRunner.Run<Benchmarks_StorageKey>();
//BenchmarkRunner.Run<Bechmarks_ReadOnlyStoreView>();
//BenchmarkRunner.Run<Bechmarks_LevelDB>();
BenchmarkRunner.Run<Benchmarks_StoreCache>();
18 changes: 18 additions & 0 deletions src/Neo.IO/IKeySerializable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (C) 2015-2025 The Neo Project.
//
// IKeySerializable.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

namespace Neo.IO
{
public interface IKeySerializable
{
byte[] ToArray();
}
}
Loading