Comments 29
Если вам кажется необходимым перевести какой-либо материал по программированию, которого ещё не было на Хабре — пишите в личку.
Ооочень полезная статья. К прочтению.
После прочтения ещё будет не лишним поглядеть доклад уже упомянутого в посте Вячеслава Егорова — www.youtube.com/watch?v=65-RbBwZQdU
Что-то я сомневаюсь, что картинка со сравнением быстродействия массивов подписана правильно. Скорее всего там всё-таки не число операций в секунду, а время выполнения и, соответственно, чем больше, тем хуже. А значит и вывод сделанный из картинки — не верен.
это jsperf.com'овые графики, он все выражает в операциях в секунду.
Я вижу, что это jsperf, поэтому не знаю, почему закралась ошибка, но предпочитаю верить своим глазам и логике. Да и любой желающий может сходить по имеющейся в тексте ссылочке на тот же jsperf и провести тесты самостоятельно, чтобы убедиться в том, что результаты противоположны. Например, у меня для chrome.39 пустой массив выдал 30 op/sec, а предзаполненный 133 op/sec. Для firefox.35 аналогично 81/87, opera.12 — 51/54, safari.5 — 45/46
Но можно и просто увидеть нелогичность картинки — если ей верить, то у всех браузеров с появлением новых версий производительность падает. Иногда так бывает, но так не может быть для всех браузеров.
Но можно и просто увидеть нелогичность картинки — если ей верить, то у всех браузеров с появлением новых версий производительность падает. Иногда так бывает, но так не может быть для всех браузеров.
Лимит про 100000 для
new Array(n)
стал для V8 неактуальным после codereview.chromium.org/397593008, теперь преаллокация быстрее, потому что преалоцированный массив остается быстрым. До этой правки он превращался в словарь. Между статьёй и вами разница в 15 мажорных версий браузера и более 2 лет времени. Теперь и прототипы быстрее модулей под любым соусом, и предзаполненные массивы на полтора порядка быстрее.
«Не удаляйте элементы массивов» — а если это необходимо?
Нельзя чтоб образовывался 'пробел' в массиве, окей это понятно, но как поступить лучше? Перестроить массив через лодашевский _.without — нормальный вариант?
«Избегайте использования delete при удалении элементов объекта» — опять же, вот нужно мне по логике удалить элемент из объекта, как лучше поступить?
Нельзя чтоб образовывался 'пробел' в массиве, окей это понятно, но как поступить лучше? Перестроить массив через лодашевский _.without — нормальный вариант?
«Избегайте использования delete при удалении элементов объекта» — опять же, вот нужно мне по логике удалить элемент из объекта, как лучше поступить?
Рекомендации про удаление относится к использованию оператора
Если у вас есть объект, который вы используете как словарь (а не как объект), то кроме удаления
Если же у вас именно объект — то лучше просто сделать
С массивом точно также — если массив уже разреженный с кучей дырок, т.е. словарь по сути дела — то пользуйтесь
Все эти рекомендации не следует применять в слепую — надо просто понимать потенциальные проблемы, профилировать и решать уже после профилировки как разбираться с hotspotами.
delete
. Если у вас есть объект, который вы используете как словарь (а не как объект), то кроме удаления
delete
ом ничего не сделаешь.Если же у вас именно объект — то лучше просто сделать
o.p = null
. С массивом точно также — если массив уже разреженный с кучей дырок, т.е. словарь по сути дела — то пользуйтесь
delete
, в противном случае либо a[i] = null
или двигайте элементы вниз (тем же splice или руками)Все эти рекомендации не следует применять в слепую — надо просто понимать потенциальные проблемы, профилировать и решать уже после профилировки как разбираться с hotspotами.
Небольшой оффтоп, недавно наткнулся на такой странный код:
Если не ошибаюсь, этот код — оптимизация для v8, обусловленная разницей внутреннего представления объектов-словарей и объектов-структур. Можете прокомментировать его и актуально ли подобное сейчас?
function toFastProperties(obj) {
function f() {}
f.prototype = obj;
return f;
eval(obj);
}
Если не ошибаюсь, этот код — оптимизация для v8, обусловленная разницей внутреннего представления объектов-словарей и объектов-структур. Можете прокомментировать его и актуально ли подобное сейчас?
Это хак связанный с тем, что V8 старается держать прототипы объектов в fast mode. Получается, когда вы присваиваете медленный объект (dictionary/slow mode) в
Сей хак актуален, если вы знаете, что у вас есть объект находящийся по какой-то причине в словарном режиме и вам хочется его превратить в быстрый объект.
f.prototype
он превращается в быстрый. Сей хак актуален, если вы знаете, что у вас есть объект находящийся по какой-то причине в словарном режиме и вам хочется его превратить в быстрый объект.
a[i] = null в данном случае разве не сделает массив массивом смешанных типов? То есть какого-то однозначно рекомендуемого метода нет, и надо выбирать компромиссное решение в зависимости от ситуации?
Разумеется если массив у нас изначально состоит из чисел (для других случаев тип элементов не отслеживается), то
null
действительно переведёт его просто в массив «чего угодно»), в этом случае a[i] = null
не подходит. Надо либо сдвигать элементы, либо писать специальный маркер в несуществующие позиции (например, a[i] = 0
). Конкретный подход зависит от назначения конкретного массива и причин, по которым нужно из него удалять элементы.А точно в Backbone есть dispose? Потому что в свежей версии такой функции нет.
Большая проблема со статьями такого рода — они все уже давно устарели. Конкретно в этой статье предлагается набор советов от 2012 года. Уже 3 года прошло, большинство из этих советов — неактуальны.
Предлагаю автору добавить вверху дату оригинальной статьи, иначе на текущий момент многие из советов можно отнести к разряду «вредных».
Большая проблема со статьями такого рода — они все уже давно устарели. Конкретно в этой статье предлагается набор советов от 2012 года. Уже 3 года прошло, большинство из этих советов — неактуальны.
Предлагаю автору добавить вверху дату оригинальной статьи, иначе на текущий момент многие из советов можно отнести к разряду «вредных».
AFAIK в Backbone никогда не было функции/метода с таким именем. Возможно это опечатка. Не знаю, что там имел в виду Эдди, но по смыслу там подходит stopListening.
В примере с генераций таблицы и добавления евентов есть косяк кажется. Переменная frag2 должна пересоздаваться внутри цикла for потому что сейчас каждая следующая строка таблицы будет содержать все td из предыдущих рядов.
Статья хорошая, но хотелось бы побольше услышать про оптимизацию именно при работе с DOM, т.к. какой бы быстрой не была функция и какой бы эффективной не была сборка мусора и распределение памяти — всё это сходит на нет, если мы собираемся много работать с DOM. В тексте статьи по этому поводу сказано фактически лишь одно — не работайте с DOM в цикле, для этого надо использовать documentFragment. Но что, если сам по себе documentFragment является очень большим, например, таблица 1000 строк по 5 колонок? У меня встраивание такого фрагмента вызывало небольшие подвисания браузера (приблизительно 0.5 с), какие бы рекомендации вы могли дать?
Я всегда думал, что браузер делает пересчет уже на следующем «тике», когда текущий фрагмент js-кода «отпустил» однопоточный интерпретатор и управление вернулось назад в ядро js. Т.е. вставите вы в DOM 1 элемент или 100 — все равно пересчет будет выполнен 1 раз, когда произойдет выход из всех запущенных вложенных функций. Я так думал. Но это, похоже, неверно в силу замечаний про DocumentFragment? Поясните, пожалуйста.
Даже метод такой был: выполнять какие-то вещи на setTimeout(..., 1), т.е. на следующем событийном цикле, когда браузер пересчитал ширины-высоты.
Даже метод такой был: выполнять какие-то вещи на setTimeout(..., 1), т.е. на следующем событийном цикле, когда браузер пересчитал ширины-высоты.
советую почитать про дерево перерисовки и работу селекторов, чтобы понимать про DOM лучше. Можно также соответствующую главку из книжки
speedupyourwebsite.ru/books/reactive-websites/
speedupyourwebsite.ru/books/reactive-websites/
Есть и непонимание по поводу того, как работает null. Установка ссылки на объект в null не обнуляет объект. ПисатьПереведённый автор здесь противоречит сам себе: мысль, изложенная до фрагмента кода, фактически противоречит мысли, изложенной после него.o.x = null лучше, чем использовать delete, но смысла это не имеет.
var o = { x: 1 }; o = null; o; // null o.x // TypeError
Если эта ссылка была последней ссылкой на объект, его затем приберёт сборщик мусора. Если это была не последняя ссылка, до него можно добраться, и сборщик его не подберёт.
Верно написано, что переменная является всего лишь ссылкою на объект. Но именно поэтому её и зануляют (обращают в null), чтобы не оставалось лишних ссылок на объект и начал работать сборщик мусора, подчистив объект. Если переменная является частью области видимости некоторого замыкания, то ссылка на объект может жить очень долго, если её не занулить — именно так и возникают «утечки памяти».
Если кратко:
1. Не используйте переменные.
2. Если очень надо их использовать, хотя бы не записывайте в них значения и нигде не используйте.
1. Не используйте переменные.
2. Если очень надо их использовать, хотя бы не записывайте в них значения и нигде не используйте.
При создании таблицы, мне кажется лишним добавление ячеек во фрагмент, почему их сразу не добавлять в элемент строки, ведь элемент строки находится во фрагменте и добавление ячеек в строки не вызовет перерисовки. Так что
frag2.appendChild(td);
мне кажется лишними телодвижениями.«простить исправить» — красиво звучит :-)
Sign up to leave a comment.
Пишем быстрый и экономный код на JavaScript