Javascript: оптимизация деталей для критического / высокотехнологичного кода Javascript

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

Скажем, вы по какой-то причине запускаете этот код: (вряд ли, я знаю, но потерпите меня)

for( var i = 0; i < 100000000000; i++ ) {
  //Do stuff
}

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

Изменить: я не обязательно говорю о цикле, а как насчет функции, которая постоянно вызывается, например onmousemove? Хотя в большинстве случаев нам не нужно использовать onmousemove, в некоторых случаях это необходимо.
Это вопрос для тех случаев.

Использование JQuery в качестве нашей библиотеки JS

Так что я бы хотел советов по оптимизации, но только наиболее необычных
- т.е. Разница в скорости между switch и if-else

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


person Matt    schedule 08.07.2009    source источник
comment
Предлагаю преобразовать этот вопрос в вики.   -  person Ates Goral    schedule 08.07.2009


Ответы (7)


Вы можете ускорить эту болтовню таким образом:

for (var i = 100000000; i--;) {
  //Do stuff
}

Меняет цикл и проверяет только

i-- 

вместо

i < 10000000 and i < 10000000 = true

Увеличение производительности на 50% в большинстве браузеров

Увидел это в отличном выступлении по Google Code @ http://www.youtube.com/watch?v=mHtdZgou0qU В докладе есть и другие замечательные приемы.

Удачи!

person Bas Dirks    schedule 24.12.2010
comment
Спасибо! Теперь вот тот, кто действительно знает, как помочь. Хотя у Nosredna есть хорошая идея избегать больших циклов, в моем случае у меня нет выбора, событие onmousemove нужно было фиксировать и каждый раз вызывать функцию, поэтому я ценю людей, которые не возвращаются и не говорят мне, что они знают, как моя программа должна работать, лучше, чем я. Я просто хотел, чтобы на мой вопрос ответили, а не критиковали. - person Matt; 12.01.2011

"И нет никакого способа обойтись без такой большой петли ..."

В реальном мире RIA вы ДОЛЖНЫ обходить большие петли. Наравне с оптимизацией важно научиться разбивать большие циклы на маленькие и дать браузеру время для работы со своим пользовательским интерфейсом. В противном случае вы доставите своим пользователям плохие впечатления, и они больше не вернутся.

Поэтому я бы сказал, что ДО того, как вы изучите фанковые оптимизации JS, вы должны знать, как разбить большой цикл на фрагменты, вызываемые setTimeout (), и отобразить индикатор выполнения (или позволить анимированным GIF-файлам зацикливаться).

Воспринимаемая скорость часто более важна, чем фактическая скорость. Мир клиента отличается от мира сервера.


При анимации узнайте, как узнать, работаете ли вы в неудачном браузере (обычно это IE), и попробуйте установить более низкую частоту кадров (или просто не анимировать). Я могу заставить некоторые анимации идти со скоростью 90 кадров в секунду в хорошем браузере, но только 15 кадров в секунду в IE. Вы можете проверить браузер, но обычно лучше использовать таймауты и часы, чтобы увидеть, как работает анимация.


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

person Nosredna    schedule 08.07.2009
comment
Речь идет не обязательно о петлях. Что, если это функция, которую часто вызывают? Например, событие onmousemove, даже если функция короткая, все равно замедляет обработку. - person Matt; 08.07.2009
comment
@Matt: в большинстве случаев вам, вероятно, не придется что-то делать, пока мышь движется или окно меняет размер (IE). Вам просто нужно будет что-то делать, когда это закончится. В этом случае вы можете отложить выполнение обработчика, чтобы он запускался только один раз. См. Это - ajaxian.com/archives/delaying-javascript-execution - person Chetan S; 08.07.2009
comment
@Chetan Sastry: Я привел событие onmousemove в качестве примера, потому что мой сайт использует движение мыши. Подумайте о чем-то похожем на автоматическое отображение координат мыши при движении, только намного сложнее. Пожалуйста, не отклоняйте вопросы, основанные на большинстве случаев, если бы все это делали, те вопросы, которые не подпадали под категорию большинства случаев, никогда не были бы решены. - person Matt; 09.07.2009
comment
@Matt: Я не отклонял ваш вопрос. Я только что ответил на конкретный случай, когда люди склонны думать, что им нужно постоянно отслеживать каждое движение мыши, но на самом деле начальная и конечная точки - это как раз то, что им нужно. Если ваш случай не подпадает под эту категорию, проигнорируйте. Остальные по-прежнему видят ваш вопрос и, надеюсь, ответят. - person Chetan S; 09.07.2009
comment
Так что это не цикл и не onmousemove. Очень сложно ответить на движущуюся цель. В разных ситуациях требуются разные техники. - person Nosredna; 09.07.2009
comment
Это onmousemove, см. Мой второй комментарий: потому что мой сайт использует перемещение мыши. - person Matt; 09.07.2009
comment
В этом случае вместо обработки в mousemove вы можете просто использовать событие mousemove для сохранения в истории событий мыши и использовать таймер для обработки. Это удержит вас от того, чтобы пользовательский интерфейс был липким - person Nosredna; 14.07.2009

Если синхронность не требуется, преобразуйте циклы в рекурсивную реализацию с помощью вызовов setTimeout.

for( var i = 0; i < 100000000000; i++ ) {
    //Do stuff
}

Может быть написано как

function doSomething(n)
{
    if (n === 0) return some_value;
    setTimeout(function(){doSomething(n-1);}, 0);
}

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

person Chetan S    schedule 08.07.2009
comment
Подробнее об этом здесь: stackoverflow.com/questions/ 957810 / - person zakovyrya; 08.07.2009

Использование split & join вместо replace:

//str.replace("needle", "hay");
str.split("needle").join("hay");
person Ates Goral    schedule 08.07.2009

Храните длинные цепочки ссылок в локальных переменных:

function doit() {
    //foo.bar.moo.goo();
    //alert(foo.bar.moo.x);

    var moo = foo.bar.moo;

    moo.goo();
    alert(moo.x);
}
person Ates Goral    schedule 08.07.2009
comment
Даже если цепочки ссылок нет, присвоение локальной переменной переменной за пределами текущей области по-прежнему полезно в циклах, потому что JavaScript сначала ищет переменные в текущей области, затем в родительской и т. Д. - person Blixt; 08.07.2009

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

Это советы по оптимизации Javascript, когда вы хотите перейти к очень мелким деталям, вещам, которые в большинстве случаев не имеют значения, но в некоторых случаях это будет иметь решающее значение:

Switch vs. Else If

Часто используемая тактика для сокращения накладных расходов, которые могут быть упущены из большой группы простых условных операторов, - это замена If-Then-Else операторами Switch.

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

Развертывание цикла

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

Подробную информацию и сравнительный анализ см. здесь.

Обратный счет петель

Измените цикл так, чтобы он вел обратный отсчет, а не вверх. Я также видел в различных документах об оптимизации, что сравнение числа с нулем намного быстрее, чем сравнение его с другим числом, поэтому, если вы уменьшите и сравните с нулем, это должно быть быстрее.

Дополнительную информацию и сравнительный анализ можно найти здесь.

Устройство Даффа
Это просто, но поначалу сложно понять. Подробнее об этом здесь.
Make обязательно ознакомьтесь с улучшенной версией ниже на этой странице.

Большая часть этой информации была процитирована прямо отсюда: Оптимизация JavaScript . Это интересно, поскольку это такой старый сайт, что он смотрит на оптимизацию с точки зрения вычислительной мощности браузера, которая у них была тогда. Хотя записанные ими тесты относятся к IE 5.5 и Netscape 4.73, их инструменты тестирования дают точные результаты для используемого вами браузера.

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

Я не предлагаю тратить часы на оптимизацию двух строк кода до 0,005 мс, но если вы будете помнить об этих методах и применять их там, где это необходимо, это будет способствовать ускорению работы сети. В конце концов, по-прежнему много людей используют IE 6 , поэтому было бы неправильно предполагать, что все браузеры могут обрабатывать одинаковую обработку.

person Matt    schedule 09.07.2009
comment
Просто попробовал эти тесты в Chrome ... некоторые, по-видимому, все еще стоят! - person ; 05.01.2011

На какой движок JavaScript мы должны ориентироваться? Если вы говорите о такой экстремальной оптимизации, это имеет большое значение. Для начала я отмечу, что трюк array.join () для конкатенации строк действительно применим только к движку Microsoft JScript; на самом деле это может дать худшую производительность на других движках JS.

person NickFitz    schedule 08.07.2009
comment
Есть хороший аргумент, что на самом деле вам нужно оптимизировать только IE. Если вы быстро запустите его в IE, в других браузерах он будет работать достаточно быстро. - person Nosredna; 08.07.2009