Я ищу реализовать O (1) поиск двоичных четырехъядерных клавиш
Я знаю, что нет истинной хэш-таблицы для javascript, вместо этого используют объекты и o (1) поиск со своими свойствами, но проблема в том, что ключи всегда преобразуются в строки.
Я подозреваю, что у меня более 10 миллионов записей в памяти, и если мне приходится полагаться на клавиши, которые являются строками, а средняя четверка - 11,5 символов, которые будут равны (10 миллионов записей * 11,5 длины * 2 байта) = 230 000 000 байтов или 230 МБ.
По сравнению с хранением в качестве int64 (10 миллионов записей * 8 байтов) = 80 000 000 байт или 80 МБ
Я знаю, что int64 не поддерживается изначально javascript, но есть библиотеки, которые могут помочь с этим в отношении выполнения побитовых операций, которые я хочу.
Теперь, хотя существуют библиотеки, которые могут работать с int64, они, в конечном счете, представляют собой объекты, которые на самом деле не представляют 8 байтов, поэтому я считаю, что не могу использовать любую библиотеку int64 в хэш-таблице, вместо этого я рассматривал возможность использования двухмерного хеша таблица с двумя int32. Первым ключом будут первые 4 байта, а второй - последние 4 байта. Это не так идеально, как 1 поиск работы, чтобы найти значение, но 2 операции, которые все еще достаточно хороши.
Однако я чувствую, что это не стоит, если все ключи хранятся в виде строк или тот факт, что все числа являются числами с плавающей запятой с двойной точностью (8 байтов), поэтому каждая запись хэша будет занимать до 16 байт (два числа "int32" ).
Мои вопросы:
<ы > 1. Если вы храните номер в качестве ключа для свойства, он займет 8 байтов памяти или преобразуется в строку и занимает длина * 2bytes? С >
- Есть ли способ кодировать двоичные ключи в двойной точности номер стандарта формата с плавающей запятой, принятый javascript, даже если число не имеет смысла, базовые биты служат цель (уникальная идентификация конструкции).
PS: Я отмечаю это с помощью nodejs, поскольку могут существовать библиотеки, которые могут помочь в моей конечной цели.
Изменить 1:
Кажется, что 1 возможно с Map()
и node 0.12.x +
Что касается числа 2, я смог использовать int64 lib (bytebuffer) и преобразовать 64-разрядный в буфер.
Я хотел просто использовать буфер в качестве ключа к Map(), но он не позволил бы мне, поскольку буфер был внутренне объектом, который каждый экземпляр действует как новый ключ для Map().
Итак, я подумал о том, чтобы вернуть буфер обратно в собственный тип, 64-битный двойной.
Использование readDoubleBE
Я читаю буфер как двойной, который представляет мой 64-битный двоичный файл и успешно позволяет мне использовать его на карте и позволяет искать O (1).
var ByteBuffer = require("bytebuffer");
var lookup = new Map();
var startStr = "123123738232777";
for(var i = 1; i <= 100000; i++) {
var longStr = startStr + i.toString();
var longVal = new ByteBuffer.Long.fromValue(longStr);
var buffer = new ByteBuffer().writeUint64(longVal).flip().toBuffer();
var doubleRepresentation = buffer.readDoubleBE();
lookup.set(doubleRepresentation, longStr);
}
console.log(exists("12312373823277744234")); // true
console.log(exists("123123738232777442341232332322")); // false
function exists(longStr) {
var longVal = new ByteBuffer.Long.fromValue(longStr);
var doubleRepresentation = new ByteBuffer().writeUint64(longVal).flip().toBuffer().readDoubleBE();
return lookup.has(doubleRepresentation);
}
Код неаккуратный и, вероятно, есть ярлыки, которые мне не хватает, поэтому приветствуются любые предложения/подсказки.
В идеале я хотел бы воспользоваться вариантами bytebuffer, чтобы у меня было еще больше экономии памяти, но я не был уверен, что это возможно на карте, потому что я не смог использовать буфер в качестве ключа.
Изменить 2:
Используя memwatch-next, я смог увидеть, что максимальный размер кучи составил 497962856 байт с помощью этого метода с помощью Set(), тогда как с помощью строки в Set() было 1111082864 байт. Это около 500 МБ против 1 ГБ, что далеко от 80 МБ и 230 МБ, не уверен, откуда приходит дополнительное использование памяти. Это ничего не стоит для этих тестов памяти, которые я использовал Set
over Map
таким образом, он должен хранить только уникальные ключи в структуре данных. (Использовать Set как средство проверки существования, где Map будет выполнять поиск)