From 2487ae7cd1626f96db5594ad005ff38aa0f7182e Mon Sep 17 00:00:00 2001 From: Jin Qiao Date: Thu, 7 Nov 2019 11:20:58 +0800 Subject: [PATCH] Replace function exceptwith and unionwith with faster functions --- neo.UnitTests/UT_FifoSet.cs | 17 +++++++++++++++ neo/Helper.cs | 40 +++++++++++++++++++++++++++++++++- neo/IO/Caching/FIFOSet.cs | 10 +++++---- neo/Network/P2P/TaskManager.cs | 8 +++---- neo/UIntBase.cs | 2 ++ 5 files changed, 68 insertions(+), 9 deletions(-) diff --git a/neo.UnitTests/UT_FifoSet.cs b/neo.UnitTests/UT_FifoSet.cs index 218aeefde2..d2e7a7af5e 100644 --- a/neo.UnitTests/UT_FifoSet.cs +++ b/neo.UnitTests/UT_FifoSet.cs @@ -27,6 +27,23 @@ public void FifoSetTest() Assert.IsTrue(set.Add(c)); CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c }); + + set = new FIFOSet(10) + { + a, + c + }; + var bb = set.ToArray(); + set.ExceptWith(new UInt256[] { a }); + CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { c }); + + set = new FIFOSet(10) + { + a, + c + }; + set.ExceptWith(new UInt256[] { c }); + CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a }); } } } diff --git a/neo/Helper.cs b/neo/Helper.cs index 7387280e2b..ac0cbf2cd3 100644 --- a/neo/Helper.cs +++ b/neo/Helper.cs @@ -1,4 +1,5 @@ -using System; +using Neo.IO.Caching; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; @@ -52,6 +53,43 @@ internal static int GetLowestSetBit(this BigInteger i) throw new Exception(); } + internal static void Remove(this HashSet set, ISet other) + { + if (set.Count > other.Count) + { + set.ExceptWith(other); + } + else + { + set.RemoveWhere(u => other.Contains(u)); + } + } + + internal static void Remove(this HashSet set, FIFOSet other) + where T : IEquatable + { + if (set.Count > other.Count) + { + set.ExceptWith(other); + } + else + { + set.RemoveWhere(u => other.Contains(u)); + } + } + + internal static void Remove(this HashSet set, IReadOnlyDictionary other) + { + if (set.Count > other.Count) + { + set.ExceptWith(other.Keys); + } + else + { + set.RemoveWhere(u => other.ContainsKey(u)); + } + } + internal static string GetVersion(this Assembly assembly) { CustomAttributeData attribute = assembly.CustomAttributes.FirstOrDefault(p => p.AttributeType == typeof(AssemblyInformationalVersionAttribute)); diff --git a/neo/IO/Caching/FIFOSet.cs b/neo/IO/Caching/FIFOSet.cs index aba54463ae..f952c886fc 100644 --- a/neo/IO/Caching/FIFOSet.cs +++ b/neo/IO/Caching/FIFOSet.cs @@ -6,12 +6,14 @@ namespace Neo.IO.Caching { - internal class FIFOSet : IEnumerable where T : IEquatable + internal class FIFOSet : IReadOnlyCollection where T : IEquatable { private readonly int maxCapacity; private readonly int removeCount; private readonly OrderedDictionary dictionary; + public int Count => dictionary.Count; + public FIFOSet(int maxCapacity, decimal batchSize = 0.1m) { if (maxCapacity <= 0) throw new ArgumentOutOfRangeException(nameof(maxCapacity)); @@ -46,11 +48,11 @@ public bool Contains(T item) return dictionary.Contains(item); } - public void ExceptWith(IEnumerable hashes) + public void ExceptWith(IEnumerable entries) { - foreach (var hash in hashes) + foreach (var entry in entries) { - dictionary.Remove(hash); + dictionary.Remove(entry); } } diff --git a/neo/Network/P2P/TaskManager.cs b/neo/Network/P2P/TaskManager.cs index f66744e92e..1f1120310a 100644 --- a/neo/Network/P2P/TaskManager.cs +++ b/neo/Network/P2P/TaskManager.cs @@ -65,11 +65,11 @@ private void OnNewTasks(InvPayload payload) return; } HashSet hashes = new HashSet(payload.Hashes); - hashes.ExceptWith(knownHashes); + hashes.Remove(knownHashes); if (payload.Type == InventoryType.Block) session.AvailableTasks.UnionWith(hashes.Where(p => globalTasks.ContainsKey(p))); - hashes.ExceptWith(globalTasks.Keys); + hashes.Remove(globalTasks); if (hashes.Count == 0) { RequestTasks(session); @@ -210,7 +210,7 @@ private void RequestTasks(TaskSession session) if (session.HasTask) return; if (session.AvailableTasks.Count > 0) { - session.AvailableTasks.ExceptWith(knownHashes); + session.AvailableTasks.Remove(knownHashes); session.AvailableTasks.RemoveWhere(p => Blockchain.Singleton.ContainsBlock(p)); HashSet hashes = new HashSet(session.AvailableTasks); if (hashes.Count > 0) @@ -220,7 +220,7 @@ private void RequestTasks(TaskSession session) if (!IncrementGlobalTask(hash)) hashes.Remove(hash); } - session.AvailableTasks.ExceptWith(hashes); + session.AvailableTasks.Remove(hashes); foreach (UInt256 hash in hashes) session.Tasks[hash] = DateTime.UtcNow; foreach (InvPayload group in InvPayload.CreateGroup(InventoryType.Block, hashes.ToArray())) diff --git a/neo/UIntBase.cs b/neo/UIntBase.cs index 22431c4cae..cc46f28402 100644 --- a/neo/UIntBase.cs +++ b/neo/UIntBase.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; namespace Neo { @@ -110,6 +111,7 @@ void ISerializable.Serialize(BinaryWriter writer) /// /// Method ToArray() returns the byte array data_bytes, which stores the little-endian unsigned int /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public byte[] ToArray() { return data_bytes;