- Вам нет дела до заказа
- Ваш ключ уже случайный
- 10 миллионов предметов
Краткий ответ
Хеш-таблица, вероятно, подойдет для вашего случая.
Скорость
Хеш-таблица (std::unordered_map
) будет O (1), если хеширование постоянное.В вашем случае O (1) выполняется, потому что вам даже не нужно хэшировать - достаточно просто использовать младшие 32 бита случайного UUID.Стоимость поиска будет аналогична одной или двум косвенным указателям.
Двоичное дерево (std::map
) будет O (log 2 n ), поэтому для 10 миллионов элементов у вас будет 24 сравнения и 24 возможных пропуска кэша.Даже для n = 4000 он будет использовать 12 сравнений, поэтому он очень быстро станет значительно хуже, чем хеш-таблица.
Основное дерево будет O ( k ), так что у вас будет максимум k сравнений и k потенциальных ошибок кэша.Очень маловероятно, что основополагающее дерево будет таким же быстрым, как хеш-таблица.В худшем случае (при условии k = несколько разумных 16 для дерева с 256 путями) он будет работать лучше, чем двоичное дерево, но гораздо хуже, чем хеш-таблица.
Так что, если скоростьявляется главным приоритетом, используйте хеш-таблицу.
Служебные данные
Типичная хеш-таблица будет содержать около 1–3 указателей на каждый элемент, если заполнена.Если не заполнен, вы, вероятно, будете тратить 1 указатель пространства на пустой слот.Вы должны быть в состоянии поддерживать его почти полным, но при этом быть быстрее, чем двоичное дерево, потому что у вас очень случайный ключ, но для максимально возможной скорости вы, конечно, захотите дать ему достаточно места.Для 10 миллионов элементов на 32-разрядном компьютере ожидайте 38–114 МБ служебных данных для полной таблицы.Для таблицы наполовину полной ожидайте 76–153 МБ.
Красно-черное дерево, наиболее распространенная реализация std::map
, будет иметь 3 указателя + 1 бул на элемент.Некоторые реализации используют выравнивание указателей для объединения bool с одним из указателей.В зависимости от реализаций и степени заполнения хеш-таблицы, красно-черное дерево может иметь немного меньшие накладные расходы.Ожидайте 114–153MiB.
Основное дерево будет иметь 1 указатель на элемент и 1 указатель на пустой слот.К сожалению, я думаю, что такие большие случайные ключи приведут к тому, что у вас будет очень много пустых слотов к краю дерева, поэтому он, вероятно, будет использовать больше памяти, чем любой из вышеперечисленных.Уменьшение k может снизить эти издержки, но также снизит производительность.
Если важны минимальные издержки, используйте хэш-таблицу или двоичное дерево.Если это приоритет, используйте полную хеш-таблицу.
Обратите внимание, что std::unordered_map
не позволяет вам контролировать, когда он изменит размер, поэтому получить одну полную будет сложно. Boost Intrusive имеет очень приятную реализацию unordered_map
, которая предоставит вам прямой контроль над этим и многими другими вещами.