Как создать специфичиную структуру данных для хранения большого числа записей по беззнаковому 32 битному ключу?

Нам нужна структура, которая позволит с максимальной скоростью и минимальными потерями памяти сохранить значение по целочисленному беззнаковому 32 битному ключу. Особенность ключа в том, что он лежит в интервале от нуля о 2^32, но строго не последовательно, а непрерывными 50-100 блоками (разыне подсети).

При этом, структура должна обеспечивать возможность работы в многопоточном режиме в конфигурации - один пишет, а другой читает, по возможности с минимальным использованием блокировок.

Требования к скорости ~ 1^-6c. для записи.

Пробовал std::map, std::unordered_map, boost::unordered_map, все хорошо, но медленно.

Update:

Самое эффективное, что придумал - создать вот такую структуру:
typedef vector subnet_counters

В ней будет хранить от 256 до нескольких миллионов записей про каждый IP в заданной сети. Размер сети должен быть выделен при инициализации структуры. В процессе работы никаких выделений памяти.

Потом поместить эту структуру ее в свою очередь уже в std::map, использовав имя сети как ключ, а по ключу будет лежать уже указанынй массив.

Итого, чтобы прочесть или записать данные нужно будет сделать только следующее:
1) Найти, к какой сети относится IP (сети НЕ пересекаются)
2) Найти по ключу адрес вектора хранящего данные все IP данной сети
3) Используя адресную часть IP адреса внутри сети статически получить смещение в векторе
4) Внести/прочесть значение
  • Вопрос задан
  • 3265 просмотров
Пригласить эксперта
Ответы на вопрос 3
@throughtheether
human after all
что он лежит в интервале от нуля о 2^32, но строго не последовательно, а непрерывными 50-100 блоками (разыне подсети).
Если это IPv4-адреса, и необходимо находить longest-match, то посмотрите в сторону patricia trie. Пример промышленного использования: PySubnetTree (модуль для python, написан на C). По поводу многопоточности не могу подсказать, к сожалению.
Ответ написан
@vasiliev
Насколько я понимаю, std:::map реализована через сбалансированные деревья; unordered_map - через хэш.
Согласно замечательной таблице имеем, что в случае std::map операции поиска/записи занимают O(log N) и в среднем, и в худшем случаях; во втором случае, они занимают O(1) в среднем и O(N) в худшем. То, как будет работать хэш, во многом зависит от качества хэш-функции. Мне кажется, вам надо посмотреть именно в сторону
Ещё один момент, связанный с хэшем - число "корзин". У меня в реализации unordered_map стоит 10 по умолчанию (задаётся в конструкторе), и эта реализация, похоже, перераспределяет корзины динамически при достижении определённого числа добавленных элементов. Вот здесь показано, что правильно инициализированный unordered_map должен так же быстро работать для вставки, как и для извлечения.
Ответ написан
Если есть возможность использовать Intel TBB, то там есть concurrent_unordered_map. Если нет возможности, то почему не реализовать unordered_map самостоятельно? В самом простом случае просто делаете shared_mutex на каждый карман, над перехешированием надо будет подумать, но с другой стороны, оно вам возможно и не понадобится, просто создайте достаточно большую таблицу с самого начала.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы