Распространенные ошибки Javascript, которые сильно влияют на производительность? [закрыто]


10

На недавнем UI / UX MeetUp, который я посетил, я дал несколько отзывов на веб-сайте, который использовал Javascript (jQuery) для взаимодействия и пользовательского интерфейса - это были довольно простые анимации и манипуляции, но производительность на приличном компьютере была ужасающей.

Это на самом деле напомнило мне множество сайтов / программ, которые я видел с той же проблемой, где определенные действия просто разрушают производительность. Это в основном (или, по крайней мере, более заметно в) ситуациях, когда Javascript почти служит заменой Flash. Это резко контрастирует с некоторыми веб-приложениями, которые я использовал, которые имеют гораздо больше Javascript и функциональности, но работают очень гладко (COGNOS от IBM - один из тех, что я могу придумать не по себе).

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


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

1
@delnan, это очень верно, но, похоже, это гораздо более распространено в JS. Восприятие может быть?
Nic

1
Говорить о «сайте» становится немного скучно, когда речь идет о JavaScript. Это везде и используется для всего в эти дни.
Адам Кроссленд

@ Adam Crossland, вы абсолютно правы - в том же случае, я думаю, я помог разработчику с нативным приложением, которое также сильно зависело от jQuery.
Nic

1
Не совсем ответ на ваш вопрос, поэтому я сделаю это комментарием: я сталкивался с ситуациями, когда JavaScript много рендерил, и фактически это был механизм рендеринга браузера, который использовал секунды. Поэтому, чтобы устранить узкое место в производительности, я бы сначала искал ненужные операции рендеринга.
user281377

Ответы:


8

Распространенный убийца производительности вызывает .lengthHTMLCollection внутри forцикла:

function foo(collection) {
    for (var index = 0; index < collection.length; index++) {
        // do something awesome here
    }
}

Этот анти-шаблон приводит к тому, что размер коллекции рассчитывается при каждом прохождении цикла. Лучшим подходом является вычисление длины вне цикла:

function foo(collection) {
    var collectionLen = collection.length;
    for (var index = 0; index < collectionLen; index++) {
        // do something awesome here
    }
}

3
Зависит от браузера. Возьмите этот тест в качестве примера: в FF 5 «нормальный» тест работает почти в то же время, что и «оптимизированный» вариант. И даже в действительно старых и медлительных браузерах, что-то вроде этого, скорее всего, не будет узким местом, если JS действительно сделает что-то интересное с элементами.

1
Хм! Возможно, сегодняшние высокооптимизирующие JIT-компиляторы делают эту мудрость устаревшей.
Адам Кроссленд

4
Я не настоящий эксперт, но из спецификации ECMA видно, что длина - это просто свойство объекта массива. Так что вызов его просто возвращает значение вместо подсчета всех элементов. Не знаю, все ли реализации соответствуют спецификации, но если они это сделают, ваш код вообще не улучшит производительность.
Яцек Прусия

4
@JacekPrucia Он сказал, что коллекция , а не массив - обычно в реальном коде это будет означать список элементов DOM, возвращаемых такими функциями, как document.getElementsByTagName. Функция возвращает лайв, nodeListкоторый пересчитывает его длину при каждом .lengthобращении к свойству.
И Цзян

2
@JacekPrucia тест это повышение производительности. Поиск недвижимости не дешево.
Рэйнос

4

Нет, проблема не в том, что JS используется для замены флэш-памяти. Если вы не уверены в этом, документируйте свои действия в ActionScript: он очень близок к JS.

Как убийца производительности, вы можете найти несколько плохих практик:

  • Прикрепите обработчик событий к непрерывному событию, такому как прокрутка, перемещение мыши или подобные вещи. Это имеет 2 недостатка: если событие не достаточно запущено, ваше приложение не будет реагировать. Если он срабатывает слишком много, вы будете иметь огромную нагрузку на процессор бесплатно.
  • Выполнение синхронных вызовов AJAX. Javascript не является многопоточным, поэтому, когда часть JS чего-то ждет, ваше приложение зависает. Вам лучше использовать асинхронные вызовы AJAX и таким же образом использовать setTimeout / setInterval, чтобы разделить длительную фазу вычислений и сохранить реактивность вашего приложения.
  • Высокая сложность алгоритма, как и в любых других языках.

Я видел более чем несколько приложений, которые пытались вращать, облегчать или анимировать изображения в полном браузере и с треском проваливаться в процессе - отсюда и комментарий о замене Flash :)
Nic

Поскольку первая буква A в AJAX означает асинхронную, технически это не AJAX, если она синхронная, но ваша точка зрения остается хорошей.
Карл Билефельдт

Да, верно, это не совсем AJAX. Но в любом случае этого нужно избегать: D
deadalnix

3

Я дал несколько отзывов на веб-сайте, который использовал Javascript (jQuery) для его взаимодействия и пользовательского интерфейса - это были довольно простые анимации и манипуляции, но производительность на приличном компьютере была ужасной.

Одной из самых больших проблем с производительностью является использование абстракций высокого уровня (таких как jQuery) без понимания базовой модели DOM и модели анимации CSS3 (или canvas, или svg).

Если вы не знаете , как сделать это без абстракций , то у вас есть абсолютный ноль знание о том , что методы быстро или медленно.

Изучите JavaScript, изучите DOM. Как только вы знаете эти два и знаете, что ваши абстракции делают под капотом, вы можете использовать их эффективно. Конечно, большую часть времени вы понимаете, что абстракция заключается в замедлении и просто делаете это вручную без библиотеки.


1

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

Из обзоров кода, частью которых я был, основные проблемы, как правило, связаны с рендерингом CSS. Для новых разработчиков JS мы склонны видеть слишком много переменных, используемых в глобальной области видимости.

Кроме того, неправильное закрытие может часто вызывать утечки памяти. Тем не менее, большинство современных сред Javascript предотвращают подобные проблемы, если ваш код следует структуре.


0

Вот быстрая ссылка, которую я нашел год или около того назад о написании лучшего кода jquery: http://net.tutsplus.com/tutorials/javascript-ajax/10-ways-to-instantly-increase-your-jquery-performance /

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

Пример:

var table = $("#data").dataTable(.....);

DataTables - это плагин jQuery, который мы используем для создания хороших сеток. Как бы то ни было, в таблице было около 5 тыс. Строк, применяя плагин DataTables и затем сохраняя его в переменной таблицы, что фактически привело к тому, что FireFox и IE предупредили, что выполнение сценария занимает слишком много времени. Мораль истории, только кешируй данные, если нужно.


1
Похоже, DataTables является действительно неэффективным / плохим плагином, а не проблемой с кэшированием. 5к это ничего.
Райнос

@Raynos: он сказал 5k строк , а не 5 килобайт данных. «Строка» может быть очень большой вещью.
Крис Фармер

@ChrisFarmer Если «строка» очень большая вещь, то у вас другая проблема.
Райнос

-1

Из того, что я слышал, forциклы вычислительно быстрее, чем циклы jQuery $.each().


3
Это ответ на шутку?
Рэйнос
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.