LINUX.ORG.RU
Ответ на: комментарий от anonymous

Было б на чём ещё писать фронтэнд...

Bahamut
() автор топика

Потому что строки в жс immutable и хранятся в пуле.

a + b реально не конкатенирует строки, а создаёт конструкцию вида `[&a, &b]` и кладёт её в пул.

Если ты будешь делать `var a = "; for (...) a += 'x';` посимвольно и долго, ты получишь в пуле стопицот версий всего этого добра и это выжрет всю память со скоростью самолёта.

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

Чтобы не выжирать память длинными посимвольными строками, строки надо собирать стрингбилдерами, в жс для этого можно использовать массив: var a = []; for (...) a.push('x'); ... a.join("); — создаст тебе простую строку. Для остальных языков гугли string builder.

Но для малого количества конкатенаций длинных строк (что в целом типичный юзкейс для жс) такая организация их хранения даёт заметный выигрыш.

ChALkeR ★★★★★
()
Последнее исправление: ChALkeR (всего исправлений: 3)
Ответ на: комментарий от ChALkeR

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

loyd
()
Ответ на: комментарий от ChALkeR

Они не просто иммутабельные, это примитивные типы. Насколько я понимаю, любые «foo» и «foo» всегда ссылаются на один и тот же кусок памяти

asteroidcollide
()
Ответ на: комментарий от ChALkeR

Почему

reduce
работает быстрее
var res = ''; for (var s of arguments) { res += s; }
в три! раза?

Почему

forEach
с каллбэком работает быстрее
for (let s of arguments) { res += s; }
?

anonymous
()
Ответ на: комментарий от anonymous

arguments довольно плохая вещь. Особенно, если ты не в 'use strict'

ChALkeR ★★★★★
()
Ответ на: комментарий от anonymous

Потыкай флагами --trace-opt --trace-deopt это всё и посмотри что там как.

ChALkeR ★★★★★
()
Ответ на: комментарий от anonymous

А при использовании же в for-of переменных с блочной областью видимости, проигрывает в два-три раза как раз reduce.

https://pp.userapi.com/c837522/v837522199/7881a/njPPNMXhSWA.jpg

Да и вообще, нативные forEach/reduce/map никогда не были быстрее циклов, потому что в них происходят лишние проверки и оверхед на сами вызывы коллбеков. Была отдельная библиотека с fast методами, где таких проверок не было. Она была быстрее нативных методов, но вовсе не быстрее циклов.

anonymous
()
Ответ на: комментарий от anonymous
var a = []; for(var i = 0; i < 10000; i++) {a.push("_" + i + "sadsadsadasdsadasdsa")}
function time(f) {let d = Date.now(); for(var i = 0; i < 1000; ++i){f()}; let res = Date.now() - d; console.debug("Execute ", f.toSource(), " in ", res/1000, "s" )}
time(() => {a.reduce((p, c) => p += c);}); time(() => {a.reduce((p, c) => p + c);})
Execute  () => {a.reduce((p, c) => p += c);}  in  0.719 s 
Execute  () => {a.reduce((p, c) => p + c);}  in  0.652 s

«что-то»

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Это никак не повлияло на суть. reduce не быстрее цикла. И уж тем более, не быстрее его в три раза.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.