Эффективная реализация trie для .net

Я ищу реализацию trie для .net.

Я планирую использовать его в качестве структуры индекса для моего пула объектов в памяти. Он не обязательно должен быть потокобезопасным (поскольку его будет обновлять только один поток), но он должен корректно и с постоянной производительностью обрабатывать как минимум 20 миллионов элементов.

Те, что я нашел в сети, кажутся образцами кода или игрушечными проектами. Итак, я действительно ищу реализацию качества продукции. Коммерческие библиотеки тоже подойдут, если они есть.

PS: я выбрал попытки, так как кажется, что реализации хеш-таблиц, которые я видел, используют слишком много памяти и имеют тенденцию вызывать фрагментацию памяти, поскольку они основаны на массивах. Любой такой контейнер с характеристиками поиска O(1) и мягкими характеристиками использования памяти для большого количества элементов также может быть в порядке.

Спасибо,


person Kemal Erdogan    schedule 17.01.2012    source источник
comment
20 миллионов штук? Использование памяти trie в этом случае почти гарантированно будет больше, чем словарь/хеш-таблица - возможно, на несколько порядков... Также вам действительно нужен пул объектов в памяти? Собственное управление памятью .Net довольно надежно.   -  person Andras Zoltan    schedule 17.01.2012
comment
Какие стандартные структуры данных вы пробовали и соответствовали вашим потребностям? (объяснить, почему)   -  person Peter    schedule 17.01.2012


Ответы (2)


По моему личному мнению, попытка предугадать собственное управление памятью .Net - это не та практика, которую я бы рекомендовал. Вы просто не можете осуществлять тот уровень контроля над распределением памяти, который возможен в собственном сценарии, но в равной степени вам и не нужно. Я был одержим желанием сделать это, когда впервые перешел с C++ (где я регулярно работал со своими собственными кучами и писал подпрограммы локализации памяти и т. д.), но быстро стало очевидно, что мне это просто не нужно и < em>может я.

Например, у вас может быть массив MyPooledObject в нижней части вашего дерева, но если это ссылочный тип, то вы только что получили массив ссылок, где фактическая память для каждой из них находится где-то еще, что вы можете не контролируется (если только вы не адаптируете свой собственный хост для среды выполнения).

Вместо этого остается использовать тип значения, но они просто не подходят для использования в объединенном сценарии, потому что настраиваемые типы значений должны быть неизменяемыми (я могу сказать это безопасно, не оправдывая этого - просто гуглите «неизменяемый» и «структура», ориентируясь на сайт :stackoverflow.com, чтобы увидеть больше), и поэтому не стоит рассматривать их как объекты многократного использования.

Если вам нужна индексированная коллекция объектов в .Net, каждый из которых распознается с помощью ключа с поддержкой хеширования, используйте словарь.

Если у вас слишком много объектов, чтобы поместиться в памяти, то:

1) Получить больше памяти

2) Использовать базу данных и кэшировать ее локальные сегменты

Или и то, и другое: вы можете изучить AppFabric и его функции кэширования, которые Таким образом, вы можете создать ферму машин, предназначенных для запуска кэшей в памяти миллионов объектов. Стоимость оборудования, вероятно, будет меньше, чем стоимость разработки собственного решения для управления памятью для .Net :)

person Andras Zoltan    schedule 17.01.2012
comment
На самом деле я пробовал все реализации хеш-таблиц в .net framework, а также в библиотеке C5. Проблема с хеш-таблицами заключается в том, что они основаны на массивах. Как только их буферы массива заполнены, они пытаются перераспределить всю структуру с удвоенной емкостью. Поэтому, если в системе происходит много добавлений, это приводит к фрагментации памяти и ошибкам нехватки памяти, поскольку смежные области памяти быстро истощаются. Реализация хеш-таблицы, которая не работает таким образом, была бы очень полезной, но ее тоже не удалось найти. - person Kemal Erdogan; 17.01.2012
comment
Массив ссылок примерно равен размеру массива указателей. В вашем случае 20 миллионов = около 80 МБ или 160 МБ в 64-битной среде. Почему бы просто не создать хеш-таблицу или словарь с большой начальной емкостью? - person Andras Zoltan; 17.01.2012
comment
Спасибо, Золтан, и извините за поздний ответ. Должно быть, я пропустил, что не ответил на ваши предложения. Это действительно то, как я закончил, то есть предварительно выделил большой кусок, близкий к моему окончательному размеру, и позволил ему поиграть, используя стандартный словарь. Я также экспериментировал с сокращением словарного ключа на более мелкие части и сохранением иерархии словарей. Это также работает, но отслеживать под-подсловари сложно и не дает большого преимущества, если я знаю приблизительную цифру максимального размера. Итак, в конце концов я выбрал простой подход. - person Kemal Erdogan; 09.06.2016

Взгляните на эту библиотеку: TrieNet

using Gma.DataStructures.StringSearch;

...

var trie = new SuffixTrie<int>(3);

trie.Add("hello", 1);
trie.Add("world", 2);
trie.Add("hell", 3);

var result = trie.Retrieve("hel");
person George Mamaladze    schedule 31.08.2017
comment
Пожалуйста, не просто публикуйте какой-либо инструмент или библиотеку в качестве ответа. По крайней мере, продемонстрируйте как он решает проблему в самом ответе. - person paper1111; 31.08.2017
comment
1. Это как раз ожидаемый ответ на вопрос. Так почему бы не? 2. Я являюсь автором этой широко используемой библиотеки и в репозитории достаточно примеров и документации. - person George Mamaladze; 31.08.2017
comment
См. meta.stackexchange.com/questions/8231/. Вы должны включить пример в ответ. - person paper1111; 31.08.2017