#javascript #node.js
#javascript #node.js
Вопрос:
У меня есть переменная с именем uids
var uids = [];
Затем я записываю некоторое значение в его свойство
uids[16778923] = "3fd6335d-b0e4-4d77-b304-d30c651ed509"
Но перед этим
if (!uids[user.id]) {
uids[user.id] = generateKey(user);
}
Эта вещь ведет себя нормально. Если я попытаюсь получить значение этого свойства
uids[currentUser.id]
Это даст мне значение этого свойства. Если я попытаюсь вызвать некоторые методы, такие как
Object.keys(uids);
Это даст мне то, что я ожидал. И здесь возникает загадка…
uids;
RAM отдыхает по частям. Посмотрите, как узел потребляет оперативную память
Сейчас я очень смущен. Что не так?
Комментарии:
1. У вас есть пример, который вызывает проблему, и мы можем легко запустить? Пробовали ли вы какое-либо профилирование на стороне узла, чтобы увидеть, куда уходит эта память?
2.
.length
Из-за назначения ваш массив будет иметь16778924
значение. Это может иметь значение. Я предполагаю, что массив будет разреженным, поэтому я не уверен, почему это так. Пробовали ли вы вместо этого обычный объект?var uids = {}
3. @squint спасибо! Теперь это работает
4. согласен с @squint, в JS объекты были бы лучше для создания чего-то вроде карты.
Ответ №1:
Это потому, что вы создаете огромный массив, и узел зарезервирует для него память — кто знает, что произойдет. Я бы сказал, что это сценарий, в котором вы бы использовали Map
(или обычный объект, но Map
здесь он чувствует себя лучше.
var uids = new Map();
var key = 456464564564654;
if (! uids.has(key)) {
uids.set(key, generateKey(user))
}
Ответ №2:
Вы создаете пустой массив (длина равна нулю), затем присваиваете некоторое значение произвольному индексу. Это приведет к увеличению размера массива до размера индекса и присвоению значения этому индексу. Посмотрите на этот пример, используя node.js REPL:
> var a = []
undefined
> a[5] = "something"
'something'
> a
[ , , , , , 'something' ]
> a.length
6
Вместо создания массива вы могли бы создать Map() или обычный объект javascript (singleton). Объекты Javascript ведут себя как карты, но в качестве ключей можно использовать только строки. Если вы назначаете число ключом, javascript автоматически преобразует его в строку.
Лично я бы выбрал объекты, потому что они работают лучше. Создание экземпляра объекта занимает больше времени, чем создание экземпляра Map (и не похоже, что вам нужно создавать несколько групп «uid»), но после завершения добавление новых ключей и извлечение значений из любого ключа быстрее при использовании обычных объектов. По крайней мере, так обстоят дела в моем node.js версия 6.7.0 на ubuntu 14.04, но вы могли бы попробовать сами. И это также внесло бы наименьшие изменения в ваш код.
var uids = {} // common/ordinary empty javascript object instead of array.
if (!uids[user.id]) { // getting value from one key works the same.
uids[user.id] = generateKey(user) // assignment works the same.
}
////
uids[16778923] = "3fd6335d-b0e4-4d77-b304-d30c651ed509" // key will be "16778923".
uids[16778923] // getting value for key "16778923" can be done using 16778923 instead of "16778923".
////
uids[currentUser.id] // still returning values like this.
Object.keys(uids) // still returning an array of keys like this. but they are all Strings.