Сравниваем скорости создания копий массивов в JavaScript разными способами

  Рет қаралды 2,952

WebDev с нуля. Канал Алекса Лущенко

WebDev с нуля. Канал Алекса Лущенко

Күн бұрын

Пікірлер: 27
@KadochnikovK
@KadochnikovK Ай бұрын
Фантастическая скорость работы slice связана с оптимизацией Copy-on-Write. Эта оптимизация, при которой копирование больших данных откладывается до тех пор, пока одна из копий не будет изменена. То есть, по сути, создается не копия массива, а новая ссылка на память, в которой хранится ссылка на исходный массив. И лишь в момент изменения нового массива происходит фактическое копирование. Чтобы в этом убедиться, можно в цикле со slice после копирования производить операцию, изменяющую новый массив (например, push). Тогда вся магия исчезает и slice начинает работать не быстрее map или for.
@davidhayrapetyan7039
@davidhayrapetyan7039 Ай бұрын
а можно пожалуйста пример кода ? изменяя массив после копирования (10000 элементов) у меня slice (2s) а map(2.7s) chatGPT объясняет что в slice не передается функция и оно не вызывается для каждого элемента по этому он быстрее
@KadochnikovK
@KadochnikovK Ай бұрын
@@davidhayrapetyan7039 ну 2 секунды и 2,7 секунд это не такая большая разница. Slice, конечно, быстрее, чем map. Но не в тысячи раз.
@ВиталийБоднар-е1я
@ВиталийБоднар-е1я 2 ай бұрын
Алексей в первом методе создания копии использовал push, что для данной задачи может быть оптимизированно, если написать это немного иначе, то результат будет получше: for (let i = 0; i < 100000; i++) { const m = new Array(array.length) for (let k = 0; k < array.length; k++) m[k] = array[k] } Просто push() как будто добавляет в оригинальный массив элементы изменяя его длину, но на самом деле, это не совсем правда, при работе этого метода JS периодически создаёт новые массивы с удвоенной длиной когда длины нынешнего массива не хватает (JS изначально создаёт массивы с запасом длины). При этом приходится копировать элементы со старого массива в новый и запускать garbage collection что затратно. Если изначально создать массив нужной длины то время сократится вдвое. Но конечно slice() тут всё равно вне конкуренции. И видео всё равно интересное и познавательное.
@itgid
@itgid 2 ай бұрын
@@ВиталийБоднар-е1я огромное спасибо. Действительно не подумал по индексу. Насколько быстрее получается у вас?
@SerzhNesteruk
@SerzhNesteruk Ай бұрын
Спасибо за уместное замечание. Хотя тут есть ещё вторая сторона медали. Мы конечно экономим на реалокациях массива в памяти. Но вот массивы созданные через конструктор Array (с указанием длины) определяются рантаймом V8 как разреженные. И при дальнейшей работе с этими массивами возможна ощутимая просадка производительности. Поэтому поверхносное клонирование массива лучше таки делать через slice или даже через spread (как ни странно).
@ВиталийБоднар-е1я
@ВиталийБоднар-е1я Ай бұрын
@@itgid не намного - в 2 раза быстрее чем при использовании push()
@KadochnikovK
@KadochnikovK Ай бұрын
Чтобы спред опреатор в браузере работал быстрее в таких условиях, его можно использовать в таком виде - Array(arr.length).fill(...arr). Да, скорость все еще будет ниже чем у slice, но не в десятки тысяч раз, а, всего лишь, в сотни. А при однократном копировании одного огромного массива на 50 000 000 элементов разница и вовсе отсутствует, только в этом случае использовать нужно [...arr], иначе произойдет переполнение стека.
@AlexGabber
@AlexGabber Ай бұрын
Смущает слайз, а не помещает ли он просто ссылку в переменную, вместо копирования? Для массива с примитивными данными подходит все, для глубокой структуры только стрингифай парс и структуредклон (жаль не был разобран)
@urakend
@urakend Ай бұрын
Это легко проверить.Увеличить объем массива и сравнить время.
@AlexGabber
@AlexGabber Ай бұрын
@@urakend а причем тут время? вопрос создает ли клон слайз или просто ссылается на текущий объект произведя нулевую мутацию
@urakend
@urakend Ай бұрын
@@AlexGabber ,а притом,что во втором случае оно не измениться...
@xthemey
@xthemey Ай бұрын
Самое интересное, что результаты для браузера и для Node js отличаются) //Node Js 3408 loop for 3339 loop while 1 spread 1 slice 1998 map 3331 filter 2 Array.from 25202 JSON.parse(JSON.stringify) 3 concat 1474 copy by index to new Array() /// 24624 structuredClone 184778 Object.assign // Browser 2485 'loop for' 2455 'loop while' 21746 'spread' 3 'slice' 3870 'map' 2864 'filter' 16841 'Array.from' 16796 'JSON.parse(JSON.stringify)' 2 'concat' 622 'copy by index to new Array()' /// 15350 'structuredClone' 140473 'Object.assign'
@swayok
@swayok Ай бұрын
Всегда использовал slice вместо новомодных свистелок и, видимо, не зря. Но вообще странно что Array.from() такой медленный.
@zestlife5792
@zestlife5792 2 ай бұрын
Concat?
@ГаляКравченко-у2ш
@ГаляКравченко-у2ш 2 ай бұрын
Я взагалі в шоці 😮
@ИванГоденов-и7д
@ИванГоденов-и7д Ай бұрын
Для чистоты эксперимента нужно движок JS было указать и его версию, т.к. в других движках могут присутствовать свои оптимизации и результат может кардинально отличаться. Например, в V8 есть оптимизации для цикла for и while для большого количества итераций. В том же V8 итерационные методы массивов базируется на reducer-е, т.е., поэтому их производительность будет примерно одинаковой. И очень многое также зависит от того как движок JS работает с памятью при создании и изменении массивов. Одно дело создавать массив с числами или строками без дырок и совершенно другой случай, когда в массиве встречаются дырки или данные другого типа. В спецификации для этих случаев создаются вообще разные виды массивов. И работа с ними будет существенно отличаться.
@itgid
@itgid Ай бұрын
Увы чистого эксперимента не получится. Если же провести эксперимент с научной точностью то данное видео просто смотреть никто не будет. Повторял и буду повторять - есть фреймворк PHP Yii2. Его разрабочтик записывает видео длинной 3-4 часа наполненные очень крутой информацией, бесценной. У него 100-150 просмотров за много лет. Нужно понимать что даже shorts нарезанный с марвел набирает больше чем видео по программированию, поэтому приходится работать в сжатых рамках на грани "попса-программирование-популизм".
@Nine_Tails
@Nine_Tails 2 ай бұрын
forEach то же, что и for?
@1654045
@1654045 2 ай бұрын
вот у меня на 100 000. Slice: 0.40 ms Spread: 11.80 ms Array.from: 6.10 ms Concat: 0.60 ms For Loop: 44.50 ms
@_AnthonyD_
@_AnthonyD_ 2 ай бұрын
А почему так происходит-то? Компилятор лучше оптимизирован для slice? или в чем дело?
@KadochnikovK
@KadochnikovK Ай бұрын
Фантастическая скорость работы slice связана с оптимизацией Copy-on-Write. Эта оптимизация, при которой копирование больших данных откладывается до тех пор, пока одна из копий не будет изменена. То есть, по сути, создается не копия массива, а новая ссылка на память, в которой хранится ссылка на исходный массив. И лишь в момент изменения нового массива происходит фактическое копирование. Чтобы в этом убедиться, можно в цикле со slice после копирования производить операцию, изменяющую массив (например, push). Тогда вся магия исчезает и slice начинает работать не быстрее map или for.
@Tar2ga
@Tar2ga Ай бұрын
зачем в цикле на 10 тысяч раз делать map, filter, spread и т.д.?
@SerzhNesteruk
@SerzhNesteruk Ай бұрын
Это очень правильный вопрос! ☝️ JIT-компиляторы современных JS-рантаймов могут оптимизировать выполнение некоторых сценариев при их многократном выполнении (например, несколько тысяч раз). Такие оптимизации, как loop unrolling (развертка циклов) или dead code elimination (удаление мертвого кода), могут существенно влиять на результаты бенчмарков или даже заметно их искажать. Использование литеральной записи массива вместо генерации массива со случайными данными также может добавить искажения в результаты бенчмарков. Литеральные массивы имеют фиксированную структуру, и их поведение более предсказуемо с точки зрения JIT-компилятора, что может сделать результаты менее репрезентативными для реальных сценариев с динамически изменяющимися данными. Таким образом, хотя результаты бенчмарков довольно интересны, но без учета таких факторов, как уровень оптимизации кода, прогрев JIT или предсказуемость структуры данных, их точность может быть сомнительной и не в полной мере отражать реальную производительность.
@itgid
@itgid Ай бұрын
Потому что одинарный запуск такого кода, учитывая современные скорости, не даст понять разницу. Нужно будет увеличивать массив. Задача стоит не провести академический эксперимент, а обратить внимание на разницу скоростей и заставить людей задуматься над тем, что под капотом у методовов, как они работают.
@АлексейСоколов-у3к
@АлексейСоколов-у3к Ай бұрын
на 3 млн эл [...arr] заняло 521мс, на slice 125мс
@1SkinneR111
@1SkinneR111 Ай бұрын
У меня так получилось: slice_____________________________________________________2 concat___________________________________________________2 loop while (C изначально заданной длиной массива) __517 loop for (C изначально заданной длиной массива)____ 520 map____________________________________________________893 filter___________________________________________________1658 reduce_________________________________________________1753 loop for (через push())_________________________________1762 Array.from()____________________________________________11117 spread_________________________________________________15095 JSON.parse(JSON.stringify())___________________________15617 structuredClone________________________________________16090
Сортировка массива "Беспощадный Сталин" - изучаем JavaScript
24:39
WebDev с нуля. Канал Алекса Лущенко
Рет қаралды 917
Индикатор очень плохого кода на JavaScript. Просто найди slice
25:46
WebDev с нуля. Канал Алекса Лущенко
Рет қаралды 3,7 М.
Мясо вегана? 🧐 @Whatthefshow
01:01
История одного вокалиста
Рет қаралды 7 МЛН
Sigma Kid Mistake #funny #sigma
00:17
CRAZY GREAPA
Рет қаралды 30 МЛН
Методы массивов javascript. MAP
13:35
WebDev с нуля. Канал Алекса Лущенко
Рет қаралды 22 М.
querySelector VS querySelectorAll: вы точно этого не знали
22:44
WebDev с нуля. Канал Алекса Лущенко
Рет қаралды 1,9 М.
Методы массивов JavaScript - forEach, map, filter, reduce, some, every, sort, includes, indexOf
27:47
Александр Ламков — Friendly Frontend
Рет қаралды 12 М.
как тебе будут продавать в 2025
16:22
Тихон Смирнов
Рет қаралды 464 М.
КАК УСТРОЕН TCP/IP?
31:32
Alek OS
Рет қаралды 286 М.
Мясо вегана? 🧐 @Whatthefshow
01:01
История одного вокалиста
Рет қаралды 7 МЛН