C
C#2y ago
SWEETPONY

❔ How can I store history of each tree node in memory without any leaks?

public class TreeNode
{
protected TreeNode(string part) : this(part, -1, null) {}

private TreeNode(string part, int level, TreeNode? parent)
{
Part = part;
Level = level;
Parent = parent;
Root = parent?.Root ?? this;

if(parent!=null)
MessagesCount = 1;
}
private int _historyId;
public int Level { get; }
public TreeNode? Parent { get; }
public TreeNode Root { get; }
[Reactive] public string Part {get;set;}
[Reactive] public string? Header {get;set;}
[Reactive] public string? Payload {get;set;}
[Reactive] public string? Topic {get;set;}
[Reactive] public MqttDelivery? Delivery {get;set;}
[Reactive] public int MessagesCount {get;set;}
[Reactive] public int TopicsCount {get;set;}

public ObservableCollection<ReceivedHistoryMessage> UiHistoryMessages { get; set; } = new();
public readonly Dictionary<string, TreeNode> _treeChildren = new();

public bool Add(
string[] subTopic,
MqttDelivery delivery)
=> Add(subTopic, Level + 1, delivery);

private bool Add(
string[] topic,
int level,
MqttDelivery delivery)
{
if(level >= topic.Length)
{
Topic = delivery.Topic;
Header = delivery.Header?.ToJsonString(true);
Payload = delivery.Payload?.ToJsonString(true);
Delivery = delivery;

AddToHistory(delivery);
return false;
}

var part = topic[level];
if(!_treeChildren.TryGetValue(part, out var trie))
{
TopicCount++;
_treeChildren.Add(part, trie = new TreeNode(part, level, this));
}

MessagesCount++;
trie.Add(topic, level+1, delivery);

return true;
}
}
public class TreeNode
{
protected TreeNode(string part) : this(part, -1, null) {}

private TreeNode(string part, int level, TreeNode? parent)
{
Part = part;
Level = level;
Parent = parent;
Root = parent?.Root ?? this;

if(parent!=null)
MessagesCount = 1;
}
private int _historyId;
public int Level { get; }
public TreeNode? Parent { get; }
public TreeNode Root { get; }
[Reactive] public string Part {get;set;}
[Reactive] public string? Header {get;set;}
[Reactive] public string? Payload {get;set;}
[Reactive] public string? Topic {get;set;}
[Reactive] public MqttDelivery? Delivery {get;set;}
[Reactive] public int MessagesCount {get;set;}
[Reactive] public int TopicsCount {get;set;}

public ObservableCollection<ReceivedHistoryMessage> UiHistoryMessages { get; set; } = new();
public readonly Dictionary<string, TreeNode> _treeChildren = new();

public bool Add(
string[] subTopic,
MqttDelivery delivery)
=> Add(subTopic, Level + 1, delivery);

private bool Add(
string[] topic,
int level,
MqttDelivery delivery)
{
if(level >= topic.Length)
{
Topic = delivery.Topic;
Header = delivery.Header?.ToJsonString(true);
Payload = delivery.Payload?.ToJsonString(true);
Delivery = delivery;

AddToHistory(delivery);
return false;
}

var part = topic[level];
if(!_treeChildren.TryGetValue(part, out var trie))
{
TopicCount++;
_treeChildren.Add(part, trie = new TreeNode(part, level, this));
}

MessagesCount++;
trie.Add(topic, level+1, delivery);

return true;
}
}
5 Replies
SWEETPONY
SWEETPONYOP2y ago
I have "tree-like" dictionary. The problem is following: the memory is quickly consumed and not cleared (from 100mb at start to 3gb) And the main problem in this tree is history of each node. If I remove all code inside this block: if(level >= topic.Length) (before return false;) everything will be okey and memory will clear How can I store history of each node in memory without any leaks? this in TreeNode
private void AddToHistory(MqttDelivery mqttMessage)
{
while(UiHistoryMessages.Count >= 30)
UiHistoryMessages.RemoveAt(UiHistoryMessages.Count - 1);

UiHistoryMessages.Insert(0, new ReceivedHistoryMessage()
{
Id = _historyId++,
Time = DateTime.Now,
Message = mqttMessage,
UIFormattedMessage = $"{DateTime.Now:mm:ss}, {mqttMessage.Header.ToJsonString()}"
});
}
private void AddToHistory(MqttDelivery mqttMessage)
{
while(UiHistoryMessages.Count >= 30)
UiHistoryMessages.RemoveAt(UiHistoryMessages.Count - 1);

UiHistoryMessages.Insert(0, new ReceivedHistoryMessage()
{
Id = _historyId++,
Time = DateTime.Now,
Message = mqttMessage,
UIFormattedMessage = $"{DateTime.Now:mm:ss}, {mqttMessage.Header.ToJsonString()}"
});
}
ero
ero2y ago
Are you sure the issue isn't with ToJsonString?
SWEETPONY
SWEETPONYOP2y ago
hm, no I can remove UiFormattedMessage and memory will leak anyway
ero
ero2y ago
i meant these Header = delivery.Header?.ToJsonString(true);, Payload = delivery.Payload?.ToJsonString(true); you'll have to narrow it down even more literally remove everything until the issue goes away then you have the minimum required to reproduce the problem
Accord
Accord2y ago
Looks like nothing has happened here. I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server