2013-09-20 3 views
1

Я разрабатываю одностраничное приложение, которое использует множество виджетов (главным образом сеток и вкладки) из библиотеки jqWidgets, которые загружаются при загрузке страницы. Он становится довольно большим, и я начал замечать его после , используя (я подчеркиваю, что он не начинает отставать, просто открываясь на какое-то время, но, в частности, после открытия и закрытия кучи вкладок на моем страницы, каждая вкладка содержит несколько сеток, загруженных через Ajax, которые связаны с каждым из нескольких слушателей событий) на пару минут пользовательский интерфейс становится довольно медленным, а иногда и невосприимчив, когда страница обновляется, все работает снова гладко в течение нескольких минут, затем Вернемся к лагги. Я все еще тестирую локальный хост. Моя первоначальная реакция заключалась в том, что в DOM слишком много элементов (каждая сетка создает сотни div! И у меня их много), поэтому слушатели событий, привязанные к идентификаторам, должны искать слишком много элементов и замедляться. Если это так, то это будет не так уж сложно исправить, может быть, мое предположение может быть виновником или у меня что-то страшнее?Single Page Application - Large DOM - SLOW

ОБНОВЛЕНИЕ: Здесь приведены снимки временной шкалы памяти и моментального снимка кучи. На временной шкале памяти не было никакого взаимодействия с сайтом, два больших увеличения - обновление страницы, срединная секция средней пилы просто позволяет моему сайту бездействовать.

enter image description here

enter image description here

+1

Какова временная шкала памяти в Chrome? Если он постоянно растет, у вас есть утечка памяти, и это потенциально означает много обработчиков мертвых событий и таких, которые все еще висят в памяти. –

+0

@MattGreer благодарит за то, что указала мне на временную шкалу памяти, у меня всегда есть инструменты для Chrome, но я не знал об этой функции, я довольно новый. Таким образом, график показывает, что память растет, а затем отбрасывается снова и снова, причем график почти соответствует форме, подобной лезвию пилы. Я знаю, что количество DOM довольно высокое (40 000), которое я ожидал из-за всех виджетов, но оно не выходит из-под контроля. То, что выходит из-под контроля, - это счетчик прослушивания событий, при открытии/закрытии вкладок счет начинает быстро расти! (начинается с 7000, быстро переходит в 11000+ –

ответ

2

Не видя никаких примеров кода это не так уж плохо.

Если у вас есть много селекторов jQuery, попробуйте сделать их максимально конкретными. Особенно, если вы много раз выбираете множество предметов.

Например, если у вас есть куча класса «abc», попробуйте указать перед этим, где искать - например. они находятся только в ячейках таблицы? они найдены только в тегах абзаца? Чем конкретнее вы сделаете свой селектор, тем лучше, как если бы вы указать селектор как это:

$('.class')

Тогда будет искать весь DOM для всего, что соответствует .class, однако, если вы укажете его следующим образом: $('p .class') то он будет искать только те абзацы абзацев для класса.

Другие убийцы производительности - это проводки событий, а затем их не удаляют. Если у вас есть код, который удаляет элементы, к которым привязаны обработчики событий, лучше всего удалять обработчики событий при удалении элемента. В противном случае вы начнете накапливать осиротевшие события.

Если вы делаете большой внешний вид одной страницы приложения к библиотеке, как позвоночник (http://backbonejs.org/) или угловой (http://angularjs.org/), чтобы увидеть, если это может помочь вам - они облегчить многие из этих вопросов, которые люди, которые используют простой JQuery будут работать в.

Наконец, этот пост (http://coding.smashingmagazine.com/2012/11/05/writing-fast-memory-efficient-javascript/) серьезно подходит для изложения вы можете написать быстрый, эффективный javascript и как избежать общих ошибок производительности.

Надеюсь, это поможет.

1

Не имея возможности увидеть ваш код, его немного сложно сказать точно.

Если пользовательский интерфейс немного поменяется, прежде чем он начнет лазить, тогда, похоже, что у вас есть утечка памяти где-то в вашем JavaScript. Это происходит быстро, когда вы используете множество замыканий, а также вложенные ссылки на функции и переменные, не очищая их, когда делаете с ними.

Кроме того, привязка событий ко многим элементам может быть огромной утечкой ресурсов браузера. Если возможно, попробуйте использовать делегирование делегирования, чтобы уменьшить количество элементов, прослушивающих события. Например: $ ('table'). On ('click', 'td', myEventHandler);

Будьте осторожны, чтобы убедиться, что привязки событий происходят только один раз, чтобы избежать непреднамеренных срабатываний.

Удачи вам!

2

Звучит так, будто у вас где-то есть утечка памяти. Вы используете рекурсию, которая не контролируется должным образом, или у вас есть петли, которые могут быть закончены раньше, но вы не можете вырваться из них, когда найдете что-то, что ищете, прежде чем цикл естественным образом закончится. Используете ли вы что-то вроде этого:

document.getElementById(POS.CurrentTableName + '-Menus').getElementsByTagName('td'); 

где вернулся Нодлист огромен, и вы только в конечном итоге, используя крошечную его. Эти звонки стоят дорого.

Это может быть ваш выбор архитектуры. Сотни разделов на сетку не управляются логически с помощью человеческого мозга. Вы обращаетесь к каждому div отдельно по id или это всего лишь артефакт lib, который вы используете, и загромождают DOM? Вы проверили сам DOM, когда используете его, чтобы убедиться, что вы добавляете элементы в глубь страны по ошибке и засоряете DOM с помощью нежелательной почты, которую вы не используете, заставляя DOM постоянно расти по мере использования приложения. Вы добавляете обработчики событий к элементам много раз, а не только один раз?

Для сравнения у меня также есть приложение с одной страницей (приложение Google-Chrome - многовалютный ресторанный пункт продажи) с зарегистрированными обработчиками от 1500 до 20 000 обработчиков, которые совершают вызовы на конец sqlite на сервере node.js. Я использовал в основном чистый JS, и все, кроме 50 строк HTML, написаны в JS. Я привязываю все обработчики событий непосредственно к элементу самого низкого уровня, ответственному за событие. Некоторые элементы имеют несколько обработчиков (щелчок, изменение, блокировка клавиатуры, размытие и т. Д.).

Приложение работает на скорости мигания глаз и остается таким быстрым, независимо от того, как долго он будет вверх. DOM довольно большой, и я регулярно уничтожаю и воссоздаю огромные его части (столик ресторана очищается и воссоздается для следующего сеанса), включая добавление до 1500 обработчиков событий за стол. Нажатие кнопки CLEAR и ее обновление экрана с помощью новой таблицы почти незаметно, по общему признанию, на высокопроизводительном процессоре. Моя среда разработки - Fedora 19 Linux.

+0

Сумасшедшее количество divs является побочным продуктом библиотеки виджетов, и я проверил, что элементы удаляются из DOM при удалении сетки или вкладка, содержащая сетка закрыта.Мне также нужно очистить пустых/старых прослушивателей событий. Я думаю, что это большой вклад, потому что моя страница становится ломающейся после открытия и закрытия кучи вкладок (которые содержат несколько сеток с несколькими прослушивателями событий, привязанными к каждому) не только просто будучи открытым на определенное количество времени, но после того, как некоторое время ИСПОЛЬЗУЕТСЯ ... –

+0

Я установил файлы * .js таким образом, что один из них обрабатывает создание вещей, другой обрабатывает операцию после создания , а другой - служебные аспекты. Отделив функциональность, я сломал приложение в управляемые куски, чтобы отлаживать их. Добавление обработчиков ТОЛЬКО контролируется кодом создания и не может запускаться более одного раза для каждого элемента. Начните добавлять console.log stmts для каждого создания обработчика события, чтобы узнать, удваивается ли вы на стороне создания. Добавьте больше консольных stmts в каждом обработчике, чтобы узнать, есть ли у вас события, когда вы «работаете» с приложением. –

+0

Итак, я переработал свой код, так что, когда вкладка закрыта, все виджеты уничтожены, все обработчики, созданные с помощью .on(), удаляются с .off(), а содержащая DIV очищается с помощью .empty(). Это DRAMATICALLY улучшило производительность в одиночку. Тем не менее, есть еще какие-то прослушиватели событий, которые добавляются (около 150-200), которые я не могу отследить в своем коде (опять же, может быть побочным продуктом библиотеки виджетов), есть способ увидеть ВСЕ прослушиватели событий, добавленные во время операции? –

Смежные вопросы