Количество объектов vs Полезная нагрузка при масштабировании современного проекта Javascript, который более важен?
конечно, меньшая полезная нагрузка равна меньшему количеству объектов, но, пожалуйста, прочитайте все описание ниже.
При масштабировании javascript-проекта в современном браузере, который более важен? Размер полезной нагрузки данных или количество объектов javascript в памяти. У меня есть огромная строка JSON, которую я зацикливаю и измельчая эту огромную строку на разные объекты. Строка JSON содержит много информации о путешественниках, и каждый объект Javascript обладает множеством свойств. Когда в JSON работает более 10 000 человек, браузер борется за выполнение.
Я приношу много свойств ненужным, если я могу уменьшить количество свойств, очевидно, моя полезная нагрузка будет уменьшаться, тем не менее, количество объектов может оставаться неизменным.
Число объектов JS против меньшей полезной нагрузки, что дает больше денег за деньги в отношении производительности?
Спасибо
Ответы
Ответ 1
Мне нравятся некоторые из ответов, которые я прочитал, но я думаю, что я подошел бы к вопросу об укупорке бутылки по-другому, благодаря чему я надеюсь, что вы могли бы избежать и будущих шеек бутылок.
В большинстве ответов предполагается, что количество объектов является узким местом. Я думаю, что это не так. Я считаю, что узким местом является тот факт, что цикл событий JavaScript слишком загружен.
Как вы хорошо знаете, JavaScript запускает только один поток и цикл событий.
Каждая вызываемая вами функция является обратным вызовом для таких событий.
Однако, поскольку существует только один поток, любой код на веб-странице имеет , чтобы ждать для каждого события, чтобы выполнить любую другую задачу.
Это означает, что более важно, чтобы функции JavaScript были фрагментированы (в микро-событиях/обратных вызовах), чем для любой отдельной функции, ориентированной на производительность.
В вашем случае вы оба перебираете длинную строку и выполняете действия - , не возвращая элемент управления циклу событий - это означает, что браузер должен дождаться этого большого фрагмента кода завершить, прежде чем он сможет обработать любые другие данные/события.
Вопрос о сборе/обработке данных может быть рассмотрен. Лучше ли получать много небольших сообщений (размещение, возможно, большей нагрузки на сеть/сервер)? Лучше ли получать огромную цепочку и обрабатывать ее кусками?...
... Я не знаю, это действительно зависит от других факторов, таких как дизайн сервера, дизайн базы данных, загрузка клиента, интервал обновления и т.д.
Если вы предпочитаете обрабатывать одну огромную строку, может быть, лучше обработать ее понемногу, а затем переслать ее на обратный вызов для дальнейшей обработки.
то есть. для \n
разделенной строки JSON вы можете попробовать:
function consumeString(s) {
if(s.length == 0)
return;
var sep = s.indexOf("\n");
if(sep < 0)
sep = s.length;
try {
var obj = JSON.parse(s.slice(0, sep));
console.log("processed:", obj);
} catch {
console.log("Failed... not valid JSON?:");
}
// schedule the next slice for later processing.
setTimeout(consumeString, 0, s.slice(sep + 1));
}
var text = '{ "employees" : [' + // JSON1
'{ "firstName":"John 1" , "lastName":"Doe 1" },' +
'{ "firstName":"Anna 1" , "lastName":"Smith 1" },' +
'{ "firstName":"Peter 1" , "lastName":"Jones 1" } ]}' + // END JSON1
"\n" +
'{ "employees" : [' + // JSON2
'{ "firstName":"John 2" , "lastName":"Doe 2" },' +
'{ "firstName":"Anna 2" , "lastName":"Smith 2" },' +
'{ "firstName":"Peter 2" , "lastName":"Jones 2" } ]}';
consumeString(text);
Это всего лишь схема, очевидно, но хотя она кажется менее эффективной (она тратит время на перераспределение себя и постоянно прерывается, что увеличивает вероятность промаха в кэше процессора)... это на самом деле помогает браузеру оставаться отзывчивым и улучшает воспринимаемые с точки зрения пользователя.
Ответ 2
10 000 объектов для многих JavaScript-виртуальных машин не так уж много. Ваша проблема, по-видимому, связана с тем фактом, что вы обрабатываете большое количество строк в памяти и обновляете DOM, которые являются медленными и интенсивными в памяти операциями.
Обратите внимание, что Строки неизменяемы в JavaScript, поэтому каждый раз, когда вы их рубите, вы создаете новый экземпляр этого файла в памяти. Это особенно плохо, если вы выполняете манипуляции с строками внутри цикла.
Каждая итерация приведет к созданию нового объекта String в памяти. Старый теперь отбрасывается, но не может сразу получить мусор, поэтому он будет есть память. Проблема будет ухудшаться, если вы будете манипулировать большими кусками строк. Javascript не очень хорош для выполнения этого типа длительных операций в оперативной памяти, потому что это single threaded. И такие операции связывают основной поток, который замедляет ваше приложение.
while(...) {
// this will create a new instance of fullStr in memory every iteration
fullStr = fullStr + 'str1';
}
Манипуляция DOM может быть очень медленной даже при использовании современных JS-библиотек, таких как React, если это не сделано правильно. Если вы продолжаете рендеринг новых строк, добавляя новые узлы в существующую DOM, вы увидите проблемы с производительностью. DOM-манипуляция приводит к перепланированию и перекрашиванию, причем оба из них очень медленные и интенсивно вычислительные. Каждый вызов render
может привести к полной перезагрузке и перерисовке. Если ваш компонент более высокого порядка будет отображаться при изменении прокрутки, он может заставить все дочерние компоненты повторно отображать, что замедляет вашу страницу. React действительно заботится о некоторых из этих проблем, обновляя обновления.
Другое дело, что многие люди не считают побочным эффектом использования обработчиков событий для таких событий, как mousemove
или scroll
. Каждое маленькое движение может привести к тому, что элемент на странице изменится каким-то образом, что может привести к перерисовке или перепланировке других частей DOM. Все может ухудшиться при использовании множества анимаций на странице. Эти типы обработчиков событий также могут связывать цикл событий виртуальных машин, постоянно стреляя. Для решения этой проблемы нужно было бы использовать дросселирование.
Наименее вероятно, но что-то, чтобы рассмотреть, объекты, когда они созданы, имеют дополнительные накладные расходы на поддержание количества ссылок. Для нас это может показаться, что виртуальная машина хранит объект со всеми его свойствами и значениями в непрерывном блоке памяти. Однако в reality объекты хранят ссылки на фактические значения, хранящиеся где-то в памяти. Эти накладные расходы могут быть нетривиальны для большого количества объектов.
Существует неправильное представление о том, что создание нового экземпляра class
или function
приводит к множеству служебных данных памяти, поскольку все свойства и клонирование значений. Это не true. Использование prototypes
по JavaScript сокращает использование памяти путем совместного использования одних и тех же свойств со всеми экземплярами определенного класса или функции. Вот почему прототипное наследование очень эффективно с точки зрения использования памяти. Глубокие прототипные цепи могут вызвать медленный поиск, хотя.
Ответ 3
Я дам наилучший ответ, если учесть, что мои области знаний только пересекают сферу этого вопроса, а не полностью его покрывают.
Современные компьютеры имеют иерархию памяти: основная память; два или три уровня кешей. Каждый уровень кэша меньше, но ближе к процессору (и, следовательно, быстрее), чем тот, который находится над ним.
Следовательно, с точки зрения скорости, с которой запускается программа, имеет тенденцию быть менее важным, насколько общая память используется, чем текущий "рабочий набор" - части памяти, которые программа использует при одном момент времени.
Из вашего описания это похоже на то, что разбивка большой строки JSON на множество мелких объектов поможет уменьшить размер рабочего набора большую часть времени. Если при этом у вас останется много неиспользуемых свойств, это, вероятно, не имеет значения, потому что они, вероятно, будут оставаться вне рабочего набора большую часть времени.
Это может быть полезной техникой, чтобы иметь задний фильтр для фильтрации некоторых свойств, которые не нужны, просто потому, что это уменьшит количество передаваемых данных. Тем не менее, вам нужно внимательно рассмотреть, как это будет масштабироваться; это может привести к чрезмерной нагрузке на сервер (ы).
Возможно, есть способы ускорить вашу программу путем переоценки алгоритмов, которые вы закодировали, и библиотеки (методы), которые вы используете. Могут быть некоторые методы, характерные для типичных современных движков JavaScript; Я боюсь, что это вне моего опыта.
Это может помочь ввести некоторые новые концепции в ваше приложение. Может ли быть приемлемым, чтобы обработка была уменьшена путем принятия эвристики (систематическая догадка) или уменьшенной точности?
Например, пользователи могут быть представлены промежуточные результаты на основе первого прохода, который использует только некоторые данные. Spinner (или сообщение) может использоваться, чтобы предупредить пользователя о том, что больше обработки продолжается. Когда полный набор данных был обработан, укажите его пользователю.
Или, дайте пользователю выбор "быстрых" или "глубоких" результатов; тем не менее, глубокие результаты могут быть вычислены на заднем конце (и, возможно, это может быть обработано на машинах, отличных от серверов HTTP или базы данных).
HTH и удача!
Ответ 4
Скорее всего, количество объектов JavaScript является узким местом в вашем сценарии. Вы можете сделать несколько простых элементов управления, например, проверить, попадает ли операционная система в swap. Ниже я вставляю скриншот монитора активности MacOS, где вы можете проверить использование swap. Такая же информация существует как для операционных систем Linux, так и для Windows.
![введите описание изображения здесь]()
Другой метод управления может быть, проверьте, сколько фильтров/карт/сокращений/каждой операции, которую вы делаете с вашими данными. Если вы выполняете много таких операций, это увеличивает вероятность того, что ваш код застрял с количеством объектов. Попробуйте либо уменьшить количество объектов (о которых вы уже знаете), либо уменьшить необходимость повторного итерации по объектам (например, если вы снова и снова находите одну и ту же информацию, сохраните ее на промежуточном объекте).
Ответ 5
Каждое свойство в вашем объекте само по себе является объектом. Javascript это смешно.
Пример
myObject {
prop1: 'hello',
}
Здесь у вас есть "Object" myObject
, который наследуется от прототипа Object
и несет с собой все накладные расходы объекта. Этот объект содержит свойство prop1
, которое является строкой. Строка наследует от String
, которая наследуется от Object
. Таким образом, ваша строка также несет с собой все накладные расходы объекта. Таким образом, наличие большего количества свойств должно быть примерно одинаковым в отношении использования памяти, поскольку оно содержит больше объектов.
Мне приносит много ненужных свойств, если я могу уменьшить количество свойств, очевидно, моя полезная нагрузка будет уменьшаться, тем не менее, количество объектов может оставаться неизменным.
Число объектов JS против меньшей полезной нагрузки, что дает больше денег за деньги в отношении производительности?
Я не совсем понимаю, что вы здесь имеете в виду, но похоже, что вы говорите, что вам обязательно нужны все 10 000 путешественников, но вам будет хорошо, если у каждого путешественника может быть 20 объектов вместо 100.
Да! Сделай это. Меньше данных означает меньше, чтобы отслеживать в памяти, меньший стек, чтобы проскальзывать, чтобы снова найти ваши данные и т.д. И т.д. 10000 * 20 здесь намного лучше, чем 10000 * 100.
Тем не менее, я по-прежнему призываю вас переосмыслить, имеет ли смысл вносить эти многочисленные точки данных в браузер вообще. Существует не так много случаев использования, я могу думать о том, где вы могли бы отображать все это. Гораздо лучше, чтобы ваш сервер обрабатывал данные больше, а затем просто отправьте небольшое подмножество, которое вы действительно можете поместить на экране.
Сервер может потратить свое время процессора на преобразование данных в полезные куски размера укуса, в то время как браузер тратит свое время процессора, делая пользователя шелковисто-гладким.
Ответ 6
Вы можете попытаться записать данные в IndexedDB, а затем запросить те, которые вам действительно нужны, я сомневаюсь, что вам когда-нибудь понадобится показать все объекты 10k сразу. Таким образом, вы не будете хранить большой объем данных в памяти, но вы все равно сможете получить к нему доступ. Взгляните на Dexie.js, он имеет очень простой api. Возможно, стоит попробовать.