Код: Выделить всё
abstract class TreeNode {
internal abstract Branches GetChildren();
}
class Leaf : TreeNode {
internal override Branches GetChildren() => Branches.Empty();
}
class UnaryTreeNode : TreeNode {
TreeNode child;
internal override Branches GetChildren()
{
}
}
class BinaryTreeNode: TreeNode {
TreeNode left;
TreeNode right;
internal override Branches GetChildren()
{
}
}
class VariadicTreeNode : TreeNode {
TreeNode[] nodes;
internal override Branches GetChildren()
{
}
}
Итак, очевидная простая реализация — Branches — IReadOnlyList; но это налагает штраф за распределение. Мы предполагаем, что можно каким-то образом уменьшить количество выделений при спуске по дереву до 0. Я пытался вернуть ReadOnlyMemory, но это невозможно даже с помощью закрытого отражения, поскольку привязка ReadOnlyMemory на самом деле не является произвольной.
Я развернулся и преследовал ReadOnlySpan и нашел правдоподобный подход: MemoryMarshal.CreateReadOnlySpan. Если я правильно понимаю комментарии; результирующий Span из MemoryMarshal не хранит старую ссылку на свой контейнер, поэтому тривиальная реализация не работает.
Поэтому мне остается задаться вопросом: работает ли следующее:
Код: Выделить всё
ref struct Branches {
internal object Anchor {get;init;}
internal ReadOnlySpan Span {get;init;}
}
abstract class TreeNode {
internal abstract Branches GetChildren();
}
class Leaf : TreeNode {
internal override Branches GetChildren() => default;
}
class UnaryTreeNode : TreeNode {
TreeNode child;
internal override Branches GetChildren()
{
var span = System.Runtime.InteropServices.MemoryMarshal.CreateReadOnlySpan(ref child, 1);
return new Branches { Anchor = this, Span = span };
}
}
class BinaryTreeNode: TreeNode {
TreeNode left;
TreeNode right;
internal override Branches GetChildren()
{
var span = System.Runtime.InteropServices.MemoryMarshal.CreateReadOnlySpan(ref left, 2);
return new Branches { Anchor = this, Span = span };
}
}
class VariadicTreeNode : TreeNode {
TreeNode[] nodes;
internal override Branches GetChildren()
{
return new Branches { Anchor = nodes, Span = nodes };
}
}
Я протестировал реализацию Span; это на 10–20 % быстрее, чем очевидная реализация массива.
Подробнее здесь: https://stackoverflow.com/questions/797 ... ia-memorym
Мобильная версия