Сжатие выделения путем возврата ReadOnlySpan по переменным-членам через MemoryMarshalC#

Место общения программистов C#
Ответить
Anonymous
 Сжатие выделения путем возврата ReadOnlySpan по переменным-членам через MemoryMarshal

Сообщение Anonymous »

У нас есть что-то похожее на это:

Код: Выделить всё

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
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»