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

master-2.x: Replace function exceptwith and unionwith with faster functions #1204

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions neo.UnitTests/UT_FifoSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ public void FifoSetTest()
Assert.IsTrue(set.Add(c));

CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c });

set = new FIFOSet<UInt256>(10)
{
a,
c
};
var bb = set.ToArray();
set.ExceptWith(new UInt256[] { a });
CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { c });

set = new FIFOSet<UInt256>(10)
{
a,
c
};
set.ExceptWith(new UInt256[] { c });
CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a });
}
}
}
40 changes: 39 additions & 1 deletion neo/Helper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Neo.IO.Caching;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
Expand Down Expand Up @@ -52,6 +53,43 @@ internal static int GetLowestSetBit(this BigInteger i)
throw new Exception();
}

internal static void Remove<T>(this HashSet<T> set, ISet<T> other)
{
if (set.Count > other.Count)
{
set.ExceptWith(other);
}
else
{
set.RemoveWhere(u => other.Contains(u));
}
}

internal static void Remove<T>(this HashSet<T> set, FIFOSet<T> other)
where T : IEquatable<T>
{
if (set.Count > other.Count)
{
set.ExceptWith(other);
}
else
{
set.RemoveWhere(u => other.Contains(u));
}
}

internal static void Remove<T, V>(this HashSet<T> set, IReadOnlyDictionary<T, V> 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));
Expand Down
10 changes: 6 additions & 4 deletions neo/IO/Caching/FIFOSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@

namespace Neo.IO.Caching
{
internal class FIFOSet<T> : IEnumerable<T> where T : IEquatable<T>
internal class FIFOSet<T> : IReadOnlyCollection<T> where T : IEquatable<T>
{
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));
Expand Down Expand Up @@ -46,11 +48,11 @@ public bool Contains(T item)
return dictionary.Contains(item);
}

public void ExceptWith(IEnumerable<UInt256> hashes)
public void ExceptWith(IEnumerable<T> entries)
{
foreach (var hash in hashes)
foreach (var entry in entries)
{
dictionary.Remove(hash);
dictionary.Remove(entry);
}
}

Expand Down
8 changes: 4 additions & 4 deletions neo/Network/P2P/TaskManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ private void OnNewTasks(InvPayload payload)
return;
}
HashSet<UInt256> hashes = new HashSet<UInt256>(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);
Expand Down Expand Up @@ -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<UInt256> hashes = new HashSet<UInt256>(session.AvailableTasks);
if (hashes.Count > 0)
Expand All @@ -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()))
Expand Down
2 changes: 2 additions & 0 deletions neo/UIntBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;

namespace Neo
{
Expand Down Expand Up @@ -110,6 +111,7 @@ void ISerializable.Serialize(BinaryWriter writer)
/// <summary>
/// Method ToArray() returns the byte array data_bytes, which stores the little-endian unsigned int
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte[] ToArray()
{
return data_bytes;
Expand Down