-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Fix memory leak as transactions are continuously received. #644
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds very good, this has been in the list of pending things. Thanks for this good innitiave.
I will review and test asap.
Dictionary is not needed, i changed it to a simple List, we save more memory |
@shargon I disagree with your change to a list. Lookup is slow which is what is normally being done, and we want to hold 32K or more items. |
|
Maybe we should use a |
This PR closes #509. Let's do the Bloom Filter...kkkkkkkkkkkkk |
@jsolman what do you think like this? using System;
using System.Linq;
using System.Collections.Generic;
namespace Neo.IO.Caching
{
internal class FIFOSet<T> where T : IEquatable<T>
{
private int maxCapacity;
private int removeCount;
private SortedSet<T> orderedList;
public FIFOSet(int maxCapacity, decimal? batchSize = 0.1m)
{
if (maxCapacity <= 0) throw new ArgumentOutOfRangeException(nameof(maxCapacity));
if (batchSize <= 0) throw new ArgumentOutOfRangeException(nameof(batchSize));
this.maxCapacity = maxCapacity;
this.removeCount = batchSize != null ? (int)(batchSize <= 1.0m ? maxCapacity * batchSize : maxCapacity) : 1;
this.orderedList = new SortedSet<T>();
}
public bool Add(T item)
{
if (orderedList.Contains(item)) return false;
if (orderedList.Count >= maxCapacity)
{
if (removeCount == maxCapacity)
{
orderedList.Clear();
}
else
{
for (int i = 0; i < removeCount; i++)
orderedList.Remove(orderedList.First());
}
}
orderedList.Add(item);
return true;
}
}
} |
@shargon a hashset that has linked list nodes in the values is fastest and best. (SortedSet is not optimal for this use - it uses a red black tree) |
From the document and the source code, I can see it lookup from hashtable, that's why I chosen it. |
@yongjiema I think you made a reasonable choice |
IMO memory savings is trivial and we can just revert this: 27bf008 |
I will make some benchmarks |
According to my tests, we should use a HashSet
The test is like this: const int maxCapacity = 32_000;
const int add = 64_000;
UInt160[] samples = new UInt160[100_000];
[GlobalSetup]
public void Setup()
{
var random = new Random();
for(var x = 0; x < samples.Length; x++)
{
var item = new byte[20];
random.NextBytes(item);
samples[x] = new UInt160(item);
}
}
[Benchmark]
public void SortedSet()
{
var list = new FIFOSortedSet<UInt160>(maxCapacity);
for(var x = 0; x < add; x++)
{
list.Add(samples[x]);
}
} |
@shargon you cannot use only a hash set. You will not have fifo behavior with hashset on its own. You would have to benchmark hashset with list nodes in the values and handling the links (which is basically what OrderedDictionary is doing). The fact that ordered dictionaries holds references to values is likely not going to slow it down much so writing our own data structure will just save a small amount of memory. |
One thing to note though if we do write our own data structure that uses a hashset in combination with linked list nodes, we could use a singly linked list, since we only need the FIFO behavior, which will be even a little more space efficient than the |
I understand you ... then i will revert it to use |
Anyone working on this? |
If we decide to use 2x the mempool size, i can do it |
@shargon go for it |
@yongjiema , please take a look at yongjiema#1 |
Any update? |
Closes #509