JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 08.06.24 18:27
Оценка: 6 (1)
Запускаю код в хроме.

4999999950000000
1: 320.7000000476837
4999999950000000
2: 1602.199999988079


Код практически тот же. Разница в 5 раз. Какого хрена?

        class BaseClass
        {
            constructor()
            {
                this.Value = BaseClass.Counter++;
            }

            TestMethod()
            {
                return this.Value;
            }

            static Counter = 0;
        }

        var func = function()
        {
            var sum = 0;
            for (var i = 0; i < 100_000_000; i++)
            {
                var obj = new BaseClass();
                var val = obj.TestMethod();
                sum += val;
            }
            console.log(sum);
        };

        {
            var watch = performance.now();

            func();
            
            var time = performance.now() - watch;
            console.log(`1: ${time}`);
        }

        BaseClass.Counter = 0;

        {
            var watch = performance.now();

            var sum = 0;
            for (var i = 0; i < 100_000_000; i++)
            {
                var obj = new BaseClass();
                var val = obj.TestMethod();
                sum += val;
            }
            console.log(sum);

            var time = performance.now() - watch;
            console.log(`1: ${time}`);
        }
Ад пуст, все бесы здесь.
Re: JS. Откуда такая разница в скорости?
От: kov_serg Россия  
Дата: 08.06.24 19:43
Оценка: :)
Здравствуйте, Codealot, Вы писали:

C>Код практически тот же. Разница в 5 раз. Какого хрена?

Очевидно же, не прогрелось

https://www.youtube.com/watch?v=7J7X7aZvMXQ
Re[2]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 08.06.24 19:46
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Очевидно же, не прогрелось


Если поменять порядок, скорость у каждого варианта та же.
Ад пуст, все бесы здесь.
Re[3]: JS. Откуда такая разница в скорости?
От: kov_serg Россия  
Дата: 08.06.24 19:48
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Если поменять порядок, скорость у каждого варианта та же.


А сборщик мусора вы учитываете?
Re[4]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 08.06.24 19:49
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>А сборщик мусора вы учитываете?


А как он может в этом случае на что-то влиять?
Ад пуст, все бесы здесь.
Re: JS. Откуда такая разница в скорости?
От: vsb Казахстан  
Дата: 08.06.24 20:48
Оценка:
Могу предположить, что в первом случае он заинлайнил этот нуль и этот метод. Ну цикл, видимо, не заинлайнил, но уже был близок к этому.

А потом ты разрушил всю его хрупкую картину мира и он переделал всё "как надо".
Re: JS. Откуда такая разница в скорости?
От: Muxa  
Дата: 08.06.24 21:07
Оценка:
надо байт-код посмотреть
Подозреваю что в первом случае компилятор понял что создавать объекты не нужно и можно обойтись инкрементом статического поля.

Добавь третий тест, в котором только инкремент, для проверки теории

А еще может быть что JIT решил метод func откомпилировать, тогда как основной скрипт работал в режиме интерпретатора.
Отредактировано 08.06.2024 21:13 Muxa . Предыдущая версия . Еще …
Отредактировано 08.06.2024 21:12 Muxa . Предыдущая версия .
Отредактировано 08.06.2024 21:11 Muxa . Предыдущая версия .
Отредактировано 08.06.2024 21:08 Muxa . Предыдущая версия .
Re[2]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 08.06.24 21:23
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Могу предположить, что в первом случае он заинлайнил этот нуль и этот метод. Ну цикл, видимо, не заинлайнил, но уже был близок к этому.


vsb>А потом ты разрушил всю его хрупкую картину мира и он переделал всё "как надо".


Без разницы, в каком порядке их вызывать. Если один закомментировать, тоже без разницы.
Ад пуст, все бесы здесь.
Re[2]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 08.06.24 21:28
Оценка:
Здравствуйте, Muxa, Вы писали:

M>Подозреваю что в первом случае компилятор понял что создавать объекты не нужно и можно обойтись инкрементом статического поля.


Можно как-то этого избежать?
Ад пуст, все бесы здесь.
Re[3]: JS. Откуда такая разница в скорости?
От: Muxa  
Дата: 08.06.24 21:45
Оценка:
M>>Подозреваю что в первом случае компилятор понял что создавать объекты не нужно и можно обойтись инкрементом статического поля.
C>Можно как-то этого избежать?

Наверно можно объекты в какой-то массив складывать, а затем один рандомный вывести в консоль.
Re[4]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 08.06.24 22:11
Оценка: 1 (1)
Здравствуйте, Muxa, Вы писали:

M>Наверно можно объекты в какой-то массив складывать, а затем один рандомный вывести в консоль.


Все остальное потеряется на фоне работы с массивом.
Ад пуст, все бесы здесь.
Re[2]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 08.06.24 22:14
Оценка:
Здравствуйте, Muxa, Вы писали:

M>Добавь третий тест, в котором только инкремент, для проверки теории


Дальше еще веселее.
4999999950000000
: 837.3000000119209


            var watch = performance.now();

            var sum = 0;
            for (var i = 0; i < 100_000_000; i++)
            {
                sum += i;
            }
            console.log(sum);

            var time = performance.now() - watch;
            console.log(`: ${time}`);
Ад пуст, все бесы здесь.
Re: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.06.24 07:08
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Запускаю код в хроме.

C>

C>4999999950000000
C>1: 320.7000000476837
C>4999999950000000
C>2: 1602.199999988079


C>Код практически тот же. Разница в 5 раз. Какого хрена?


Подозреваю, второй вариант не инлайнится
Re[3]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.06.24 07:10
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Дальше еще веселее.

C>4999999950000000
C>: 837.3000000119209
C>

C>
C>            var watch = performance.now();

C>            var sum = 0;
C>            for (var i = 0; i < 100_000_000; i++)
C>            {
C>                sum += i;
C>            }
C>            console.log(sum);

C>            var time = performance.now() - watch;
C>            console.log(`: ${time}`);

C>


Посмотрите, как работает интерпретатор и джит
Re: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.06.24 09:08
Оценка: 1 (1)
Здравствуйте, Codealot, Вы писали:

C>Запускаю код в хроме.

C>

C>4999999950000000
C>1: 320.7000000476837
C>4999999950000000
C>2: 1602.199999988079


C>Код практически тот же. Разница в 5 раз. Какого хрена?


Подозреваю. все что в глобальном скопе, вообще полностью исполняется интерпретатором
Отредактировано 09.06.2024 19:35 Pauel . Предыдущая версия .
Re[5]: JS. Откуда такая разница в скорости?
От: Muxa  
Дата: 09.06.24 14:19
Оценка:
M>>Наверно можно объекты в какой-то массив складывать, а затем один рандомный вывести в консоль.

C>Все остальное потеряется на фоне работы с массивом.


Тут мне кажется самое тяжелое это аллакация объекта.
Re[3]: JS. Откуда такая разница в скорости?
От: Muxa  
Дата: 09.06.24 14:22
Оценка:
оставь func с инкрементом статической переменной
Re[2]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 09.06.24 16:22
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Подозреваю. все что в гобальном скопе, вообще полностью исполняется интерпретатором


Зачем? И как это проверить точно?
Ад пуст, все бесы здесь.
Re[4]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 09.06.24 16:22
Оценка:
Здравствуйте, Muxa, Вы писали:

M>оставь func с инкрементом статической переменной


Тогда 60. То есть, это было не устранение создания объектов.
Ад пуст, все бесы здесь.
Re[3]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.06.24 19:24
Оценка:
Здравствуйте, Codealot, Вы писали:

P>>Подозреваю. все что в гобальном скопе, вообще полностью исполняется интерпретатором


C>Зачем? И как это проверить точно?


Оборачиваете в функцию, и всё, второй блок внезапно ускоряется

Оборачиваем только второй блок
class BaseClass
        {
            constructor()
            {
                this.Value = BaseClass.Counter++;
            }

            TestMethod()
            {
                return this.Value;
            }

            static Counter = 0;
        }

        var func = function()
        {
            var sum = 0;
            for (var i = 0; i < 100_000_000; i++)
            {
                var obj = new BaseClass();
                var val = obj.TestMethod();
                sum += val;
            }
            console.log(sum);
        };

        {
            var watch = performance.now();

            func();
            
            var time = performance.now() - watch;
            console.log(`1: ${time}`);
        }

        BaseClass.Counter = 0;

        (function x() {
            var watch = performance.now();

            var sum = 0;
            for (var i = 0; i < 100_000_000; i++)
            {
                var obj = new BaseClass();
                var val = obj.TestMethod();
                sum += val;
            }
            console.log(sum);

            var time = performance.now() - watch;
            console.log(`1: ${time}`);
        }) ();


Оборачиваем всё, тот же эффект
(function x() {class BaseClass
        {
            constructor()
            {
                this.Value = BaseClass.Counter++;
            }

            TestMethod()
            {
                return this.Value;
            }

            static Counter = 0;
        }

        var func = function()
        {
            var sum = 0;
            for (var i = 0; i < 100_000_000; i++)
            {
                var obj = new BaseClass();
                var val = obj.TestMethod();
                sum += val;
            }
            console.log(sum);
        };

        {
            var watch = performance.now();

            func();
            
            var time = performance.now() - watch;
            console.log(`1: ${time}`);
        }

        BaseClass.Counter = 0;

        
            var watch = performance.now();

            var sum = 0;
            for (var i = 0; i < 100_000_000; i++)
            {
                var obj = new BaseClass();
                var val = obj.TestMethod();
                sum += val;
            }
            console.log(sum);

            var time = performance.now() - watch;
            console.log(`1: ${time}`);
        }) ();
Отредактировано 09.06.2024 19:26 Pauel . Предыдущая версия .
Re[4]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 09.06.24 19:56
Оценка:
Здравствуйте, Pauel, Вы писали:

Так зачем оно может так работать?
Ад пуст, все бесы здесь.
Re[5]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.06.24 20:15
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Так зачем оно может так работать?


Затем, что джиту нужно время. Много времени.
Глобальный контекст это инициализация в основном, там ничего критичного не бывает как правило
Re[6]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 09.06.24 20:32
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Затем, что джиту нужно время. Много времени.


Если перенести тот же код в функцию, время не будет нужно?
Ад пуст, все бесы здесь.
Re: JS. Откуда - из-за var
От: rFLY  
Дата: 09.06.24 22:08
Оценка:
Здравствуйте, Codealot, Вы писали:

Замени на let и будет даже быстрее

4999999950000000
1: 412.90000009536743
4999999950000000
1: 395.40000009536743


{
            var watch = performance.now();

            let sum = 0;
            for (let i = 0; i < 100_000_000; i++)
            {
                let obj = new BaseClass();
                let val = obj.TestMethod();
                sum += val;
            }
            console.log(sum);

            var time = performance.now() - watch;
            console.log(`1: ${time}`);
        }
Отредактировано 09.06.2024 22:12 rFLY . Предыдущая версия .
Re[2]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 09.06.24 22:17
Оценка: 28 (4)
Здравствуйте, Pauel, Вы писали:

P>Подозреваю. все что в глобальном скопе, вообще полностью исполняется интерпретатором

И да и нет. Это из-за того, что переменные объявлены через var. В скопе функции это роли не играет, а вот в глобальном получаются доп расходы. Стоит заменить на let и все встает на свои места.
Re[3]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 10.06.24 01:25
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>И да и нет. Это из-за того, что переменные объявлены через var. В скопе функции это роли не играет, а вот в глобальном получаются доп расходы. Стоит заменить на let и все встает на свои места.


Ну и жесть.
Ад пуст, все бесы здесь.
Re[4]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 10.06.24 01:49
Оценка: 6 (1)
Здравствуйте, Codealot, Вы писали:

C>Ну и жесть.

Так работает var. Переменные объявленные через var (если только не объявлены внутри функции) в отличии от объявлений через let и const попадают в глобальный скоп. Можешь поставь точку останова внутри цикла и посмотреть.
Re[5]: JS. Откуда такая разница в скорости?
От: Артём Австралия жж
Дата: 10.06.24 02:08
Оценка:
Здравствуйте, rFLY, Вы писали:

C>>Ну и жесть.

FLY>Так работает var. Переменные объявленные через var (если только не объявлены внутри функции) в отличии от объявлений через let и const попадают в глобальный скоп. Можешь поставь точку останова внутри цикла и посмотреть.

Это офигенный ответ. Вообще, код ТС намекает, что он не из мира JS пришёл- элементарно линтер в проекте заругается на var и даже самому мелодичному танцору непозволит написать тот код.
Re[6]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 10.06.24 02:44
Оценка:
Здравствуйте, Артём, Вы писали:

Аё>Вообще, код ТС намекает, что он не из мира JS пришёл- элементарно линтер в проекте заругается на var и даже самому мелодичному танцору непозволит написать тот код.


Казалось бы, что мешало знатокам сразу понять, в чем загвоздка?
Ад пуст, все бесы здесь.
Re[5]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 10.06.24 02:45
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>Так работает var. Переменные объявленные через var (если только не объявлены внутри функции) в отличии от объявлений через let и const попадают в глобальный скоп. Можешь поставь точку останова внутри цикла и посмотреть.


Осталось только понять, при чем здесь скорость.
Ад пуст, все бесы здесь.
Re[6]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 10.06.24 03:26
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Осталось только понять, при чем здесь скорость.

Каждая переменная сохраняется в своем лексическом окружении, которое зависит от блока в котором переменная объявлена. По спецификации это некий объект, где сохраняются переменные и их значения (но реализация зависит от браузера). При обращении к переменной она ищется в локальном ЛО и если не находится, то во внешнем. Если не находится и там, то в еще более внешнем. И так пока не дойдет до глобального или не выдаст ошибку, что переменной не существует.
У тебя 3 блока:
1. for — отсюда начинается поиск используемых в цикле переменных, в том числе и var i
2. {} — блок в котором var sum и for
3. глобальный — здесь заканчивается, а все твои переменные попали в него (из-за использования устаревшего var). И помимо их там еще куча всякого.

Может кто-то поправит, но я вижу это так.
Re[7]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.06.24 12:24
Оценка: :)
Здравствуйте, Codealot, Вы писали:

P>>Затем, что джиту нужно время. Много времени.


C>Если перенести тот же код в функцию, время не будет нужно?


Нужно. Только время старта приложения/страницы никто не отменял. Глобальный скоп проще интерпретатором отработать, нежели ждать пока джит прогреется.
Re[6]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.06.24 12:28
Оценка: :)
Здравствуйте, Codealot, Вы писали:

FLY>>Так работает var. Переменные объявленные через var (если только не объявлены внутри функции) в отличии от объявлений через let и const попадают в глобальный скоп. Можешь поставь точку останова внутри цикла и посмотреть.


C>Осталось только понять, при чем здесь скорость.


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

Как убрать код из глобального скопа — вам показали два варианта
Re[4]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.06.24 12:42
Оценка:
Здравствуйте, Codealot, Вы писали:

FLY>>И да и нет. Это из-за того, что переменные объявлены через var. В скопе функции это роли не играет, а вот в глобальном получаются доп расходы. Стоит заменить на let и все встает на свои места.


C>Ну и жесть.


на SO такие кейсы иногда комментируют разработчики v8
Можете спросить у них, почему оптимизатор/джит не берутся за глобальный скоп
Re[7]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 10.06.24 13:49
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Как убрать код из глобального скопа — вам показали два варианта


Если ты про rFLY, то никакого отношения к джиту это не имеет.
Ад пуст, все бесы здесь.
Re[8]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.06.24 14:20
Оценка:
Здравствуйте, Codealot, Вы писали:

P>>Как убрать код из глобального скопа — вам показали два варианта


C>Если ты про rFLY, то никакого отношения к джиту это не имеет.


Что там точно происходит, вам никто кроме разработчиков V8 не скажет.

проседание производительности может происходить по следующим причинам
1. интерпретация — каждый файл до определенного выполняется интерпретатором, большинство успевает завершиться еще до того, как как рантайм решит джит подключать
2. деоптимизации — в вашем коде я их не наблюдаю
3. отсутствие инлайна — явных проблем с этим не видно
Re[7]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.06.24 14:30
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>3. глобальный — здесь заканчивается, а все твои переменные попали в него (из-за использования устаревшего var). И помимо их там еще куча всякого.


FLY>Может кто-то поправит, но я вижу это так.


Пятикратная разница — как то слишком много для поиска переменной.

Подозреваю, если дело в поиске, то замена на global.x должна дать то же пятикратное отставание
Отредактировано 10.06.2024 14:57 Pauel . Предыдущая версия .
Re[9]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 10.06.24 14:56
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Что там точно происходит, вам никто кроме разработчиков V8 не скажет.


Если замена var на let полностью убирает разницу, то при чем здесь интерпретация?
Ад пуст, все бесы здесь.
Re[10]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.06.24 16:46
Оценка:
Здравствуйте, Codealot, Вы писали:

P>>Что там точно происходит, вам никто кроме разработчиков V8 не скажет.


C>Если замена var на let полностью убирает разницу, то при чем здесь интерпретация?


Проверил, похоже это всё property lookup
globalThis.sum += val
Re[11]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 10.06.24 20:29
Оценка: 18 (1)
Здравствуйте, Pauel, Вы писали:

P>Проверил, похоже это всё property lookup

P>
P>globalThis.sum += val
P>


А если локальную переменную заменить на локальный объект (let sum = 0 на let o = {sum: 0})
//let sum = 0;
let o = {sum: 0};
for (let i = 0; i < 100_000_000; i++)
{
    let obj = new BaseClass();
    let val = obj.TestMethod();
    //sum += val;
    o.sum += val;
}

то отработает еще на 120 быстрее (интел, эдж последней версии)

с let sum = 0
4999999950000000
1: 408.7000002861023
4999999950000000
2: 390.7999997138977

против

с let o = {sum: 0};
4999999950000000
1: 409.40000009536743
4999999950000000
2: 271.69999980926514

Отредактировано 10.06.2024 20:33 rFLY . Предыдущая версия .
Re[12]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 10.06.24 21:50
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>А если локальную переменную заменить на локальный объект (let sum = 0 на let o = {sum: 0})


Это еще что за зверь?
Ад пуст, все бесы здесь.
Re[13]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 11.06.24 08:18
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Это еще что за зверь?

Кто, let o = {sum: 0}? Обычный объект со свойством sum, только объявленный в литеральной форме (JSON же знаешь как выглядит?). Создается сразу при объявлении.
    console.log("Пустой при объявлении объект");
    var obj1 = {};
    console.log(obj1);
    // Добавить свойства и методы
    obj1.prop1 = "значение Prop1";
    obj1.getProp1 = function() {
        return this.prop1;
    }
    console.log(obj1.getProp1());
    console.log(obj1);

    console.log("Тоже, но сразу со свойствами и методами");
    var obj2 = {
        prop1: "значение Prop1",
        getProp1: function() {
                return this.prop1;
            }
    }
    console.log(obj2.getProp1());
    console.log(obj2);
Re[12]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 11.06.24 08:53
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>А если локальную переменную заменить на локальный объект (let sum = 0 на let o = {sum: 0})


FLY>то отработает еще на 120 быстрее (интел, эдж последней версии)


У меня ноутбучный проц i7 22го года, отрабатывает за 900 и 600, т.е. в полтора раза стало быстрее.

А есть какое внятное объяснение этому? inline cache включается или что?
Re[13]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 11.06.24 09:13
Оценка:
Здравствуйте, Pauel, Вы писали:

P>А есть какое внятное объяснение этому? inline cache включается или что?

Вроде в ноде можно дизассемблировать при помощи следующего флага и посмотреть что там творится.
node --print_opt_code test.js

У меня тут ноды нет, так что посмотреть не могу. Могу лишь предположить, что значение свойства sum записывается в регистр, а после цикла обратно, в то время как при работе с переменной при каждой итерации используется ее адрес. А может и еще что делается.

UPD: Стало интересно и решил поэксперементировать
class BaseClass
{
    constructor()
    {
        this.Value = BaseClass.Counter++;
    }

    TestMethod()
    {
        return this.Value;
    }

    static Counter = 0;
}
console.log("без создания объекта");
{
    let watch = performance.now();
    
    let sum = 0;
    for (let i = 0; i < 100_000_000; i++)
        sum += i;
    console.log(`var_:  ${performance.now() - watch}`);
}
{
    let watch = performance.now();

    let o = {sum: 0};
    for (let i = 0; i < 100_000_000; i++)
        o.sum += i;
    console.log(`prop: ${performance.now() - watch}`);
}

console.log("с созданием  объекта");
{
    let watch = performance.now();
    
    let sum = 0;
    for (let i = 0; i < 100_000_000; i++) {
        new BaseClass();
        sum += i;
    }
    console.log(`var_:  ${performance.now() - watch}`);
}
{
    let watch = performance.now();

    let o = {sum: 0};
    for (let i = 0; i < 100_000_000; i++) {
        new BaseClass();
        o.sum += i;
    }
    console.log(`prop: ${performance.now() - watch}`);
}

без создания объекта
var_: 58.90000009536743
prop: 200.90000009536743

с созданием объекта
var_: 326.1000003814697
prop: 223.5

То есть на итог влияет new BaseClass(). С ним, даже если объект не используется, суммирование через переменную существенно просаживается.
Отредактировано 11.06.2024 12:20 rFLY . Предыдущая версия . Еще …
Отредактировано 11.06.2024 9:15 rFLY . Предыдущая версия .
Re[7]: JS. Откуда такая разница в скорости?
От: Артём Австралия жж
Дата: 11.06.24 12:10
Оценка: -1
Здравствуйте, Codealot, Вы писали:

C>Казалось бы, что мешало знатокам сразу понять, в чем загвоздка?


Такие вот знатоки, иногда лучше жевать.

Мне запомнилось, что линтер ругается на объявления var, бъёт указкой по рукам.
Re[14]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 11.06.24 14:21
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>То есть на итог влияет new BaseClass(). С ним, даже если объект не используется, суммирование через переменную существенно просаживается.


сумма — короткая операция. Вы, условно, умножаете издержки просто дёргая new BaseClass();

new BaseClass — выделение памяти, инициализация
BaseClass.Counter — лукап
++ — сравнимо с += в основном цикле
this.Value — еще один лукап
Re[15]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 11.06.24 15:11
Оценка:
Здравствуйте, Pauel, Вы писали:

P>new BaseClass — выделение памяти, инициализация

P>BaseClass.Counter — лукап
P>++ — сравнимо с += в основном цикле
P>this.Value — еще один лукап

Ты не понял или не вникал в написанное. Создание объекта не просто приводит к замедлению, а меняет время выполнения (и только при использовании переменной для суммы) на противоположный. При вычислении суммы через свойство объекта о.sum различия во времени минимальны. Повторю укороченно, если код проигнорировал:

// без new BaseClass()
    let sum = 0;
    for (let i = 0; i < 100_000_000; i++)
        sum += i;
// и
    let o = {sum: 0};
    for (let i = 0; i < 100_000_000; i++)
        o.sum += i;

// против следующего, но с добавлением new BaseClass()
    let sum = 0;
    for (let i = 0; i < 100_000_000; i++) {
        new BaseClass();
        sum += i;
    }
// и
    let o = {sum: 0};
    for (let i = 0; i < 100_000_000; i++) {
        new BaseClass();
        o.sum += i;
    }
}


вычисление переменной let sum c new BaseClass становится дороже чем аналогичное, но через o.sum, а без new BaseClass() наоборот.
Re[16]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 11.06.24 16:41
Оценка: +2
Здравствуйте, rFLY, Вы писали:

Мда, ну и муть.
Ад пуст, все бесы здесь.
Re[16]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 11.06.24 17:38
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>вычисление переменной let sum c new BaseClass становится дороже чем аналогичное, но через o.sum, а без new BaseClass() наоборот.


Что тут странного? Джит крайне ограничен, во всех платформах. чуть не так — отваливается та или иная оптимизация.
Re[17]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 11.06.24 21:24
Оценка: 25 (2)
Здравствуйте, Codealot, Вы писали:

C>Мда, ну и муть.

Почему же, просто какой-то косяк в движке. Причем связанный с обращением к статическому свойству в конструкторе через имя класса:
constructor()
{
    this.Value = BaseClass.Counter++;
}

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

Ну а пока ты можешь использовать альтернативный вариант обращения к статическому свойству в конструкторе:
constructor()
{
    this.Value = this.constructor.Counter++;
}


Итоговый вариант (по сравнению с предыдущим работает в 4 раза быстрее)

4999999950000000
1: 104.80000019073486
4999999950000000
2: 101.09999990463257


class BaseClass
{
    constructor()
    {
        this.Value = this.constructor.Counter++;
    }

    TestMethod()
    {
        return this.Value;
    }

    static Counter = 0;
}

var func = function()
{
    var sum = 0;
    for (var i = 0; i < 100_000_000; i++)
    {
        var obj = new BaseClass();
        var val = obj.TestMethod();
        sum += val;
    }
    console.log(sum);
};

{
    var watch = performance.now();

    func();
    
    var time = performance.now() - watch;
    console.log(`1: ${time}`);
}

BaseClass.Counter = 0;

{
    var watch = performance.now();

    let sum = 0;
    for (let i = 0; i < 100_000_000; i++)
    {
        let obj = new BaseClass();
        let val = obj.TestMethod();
        sum += val;
    }
    console.log(sum);

    var time = performance.now() - watch;
    console.log(`2: ${time}`);
}
Отредактировано 11.06.2024 21:39 rFLY . Предыдущая версия .
Re[17]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 11.06.24 21:35
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Что тут странного? Джит крайне ограничен, во всех платформах. чуть не так — отваливается та или иная оптимизация.

А что в sum += i оптимизировать? Впрочем причина нашлась, если интересно см. ответ выше.
Re[18]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 12.06.24 09:01
Оценка:
Здравствуйте, rFLY, Вы писали:

P>>Что тут странного? Джит крайне ограничен, во всех платформах. чуть не так — отваливается та или иная оптимизация.

FLY>А что в sum += i оптимизировать? Впрочем причина нашлась, если интересно см. ответ выше.

Я бы предположил, что джит делает не любые возможные оптимизации, а только те, на которые у него капасити хватает.
Re[18]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 12.06.24 09:12
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>Здравствуйте, Codealot, Вы писали:


C>>Мда, ну и муть.

FLY>Почему же, просто какой-то косяк в движке. Причем связанный с обращением к статическому свойству в конструкторе через имя класса:

Это не косяк, это тот же lookup, что и с поиском в глобальном скопе
Вот смотрите — если вместо class BaseClass написать const BaseClass = class { ... то получится ровно то же, что и у вас
Смотрите сами

без создания объекта
var_:  67.20000000018626
prop: 208.29999999981374
с созданием  объекта
var_:  89.90000000037253
prop: 203.90000000037253


Собственно, если просто заверуть всё в функцию, это ничем не помогает. Все дело именно в том, куда запихивается class BaseClass. Похоже, это какой то конский объект.
А вот объявление класса через const меняет дело

const BaseClass = class 
{
    constructor()
    {
        this.Value = BaseClass.Counter++;
    }

    TestMethod()
    {
        return this.Value;
    }

    static Counter = 0;
}
console.log("без создания объекта");
{
    let watch = performance.now();
    
    let sum = 0;
    for (let i = 0; i < 100_000_000; i++)
        sum += i;
    console.log(`var_:  ${performance.now() - watch}`);
}
{
    let watch = performance.now();

    let o = {sum: 0};
    for (let i = 0; i < 100_000_000; i++)
        o.sum += i;
    console.log(`prop: ${performance.now() - watch}`);
}

console.log("с созданием  объекта");
{
    let watch = performance.now();
    
    let sum = 0;
    for (let i = 0; i < 100_000_000; i++) {
        new BaseClass();
        sum += i;
    }
    console.log(`var_:  ${performance.now() - watch}`);
}
{
    let watch = performance.now();

    let o = {sum: 0};
    for (let i = 0; i < 100_000_000; i++) {
        new BaseClass();
        o.sum += i;
    }
    console.log(`prop: ${performance.now() - watch}`);
}
Отредактировано 12.06.2024 9:27 Pauel . Предыдущая версия .
Re[19]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 12.06.24 10:49
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Это не косяк, это тот же lookup, что и с поиском в глобальном скопе

Да, но в таком случае обращение к BaseClass.Counter не должно делать sum += value медленнее чем obj.sum += value. Почему высчитывание суммы через свойство объекта вдруг стало производительнее чем через обычную переменную? И там и там лукап в конструкторе класса и время просчета суммы для обоих способов должно было измениться пропорционально. Вот в этом я вижу косяк.
Re[20]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 12.06.24 11:39
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>Да, но в таком случае обращение к BaseClass.Counter не должно делать sum += value медленнее чем obj.sum += value. Почему высчитывание суммы через свойство объекта вдруг стало производительнее чем через обычную переменную? И там и там лукап в конструкторе класса и время просчета суммы для обоих способов должно было измениться пропорционально. Вот в этом я вижу косяк.


Это поведение очень похоже на работу inline cache
У него капасити крохотный, +1 лишний лукап и уже отставание в разы
Re[18]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 12.06.24 17:04
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>Причем связанный с обращением к статическому свойству в конструкторе через имя класса:


Похоже, не только в конструкторе. И еше если использовать
let obj = { sum: 0 };

а потом
let sum = 0;

(или наоборот), то производительность второго варианта просаживается раз в 5.

Муть как она есть
Ад пуст, все бесы здесь.
Re[19]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 12.06.24 17:21
Оценка:
Здравствуйте, Codealot, Вы писали:

C>(или наоборот), то производительность второго варианта просаживается раз в 5.


C>Муть как она есть


Покажите код, у меня чтото не получается воспроизвести
Re[20]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 12.06.24 20:22
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Покажите код, у меня чтото не получается воспроизвести


282.75
1442.3100000023842

Только в хроме, в фаерфоксе такого эффекта нет.

        'use strict';

        const TestsNumber = 10;
        const ItemsNumber = 100_000_000;

        function Test(func)
        {
            let totalTime = 0;

            for (let i = 0; i < TestsNumber; i++)
            {
                let watch = performance.now();

                func();

                let curTime = performance.now() - watch;
                totalTime += curTime;
            }

            console.log(totalTime / TestsNumber);
        }

        class BaseClass
        {
            TestMethod()
            {
                this.Value = BaseClass.Counter++;
                return this.Value;
            }

            static Counter = 0;
        }

        Test(function()
            {
                let obj = { sum: 0 };

                for (let i = 0; i < ItemsNumber; i++)
                {
                    let obj = new BaseClass();
                    let val = obj.TestMethod();
                    obj.sum += val;
                }
            });

        Test(function()
            {
                let sum = 0;
                
                for (let i = 0; i < ItemsNumber; i++)
                {
                    let obj = new BaseClass();
                    let val = obj.TestMethod();
                    sum += val;
                }
            });
Ад пуст, все бесы здесь.
Re[19]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 12.06.24 21:20
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Похоже, не только в конструкторе. И еше если использовать

C>
C>let obj = { sum: 0 };
C>

C>а потом
C>
C>let sum = 0;
C>

C>(или наоборот), то производительность второго варианта просаживается раз в 5.
Это следствие, а не причина. Если изменить конструктор (то, о чем писал я) или использовать модификатор const в объявлении класса (как предложил Pauel), то все начинает работать ожидаемо.
Re[20]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 12.06.24 22:16
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>Если изменить конструктор (то, о чем писал я)


Re[20]: JS. Откуда такая разница в скорости?
Автор: Codealot
Дата: 12.06.24

конструктора нет
Ад пуст, все бесы здесь.
Re[21]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 12.06.24 22:23
Оценка:
Здравствуйте, Codealot, Вы писали:

Хотя похоже, что без разницы, какой из вариантов используется. Второй всегда тормозит.
Ад пуст, все бесы здесь.
Re[22]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 13.06.24 01:11
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Здравствуйте, Codealot, Вы писали:


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

У тебя ошибка — внешний obj не используется, вместо него внутри цикла ты пишешь значение в только что созданный объект
                let obj = { sum: 0 };

                for (let i = 0; i < ItemsNumber; i++)
                {
                    let obj = new BaseClass();
                    let val = obj.TestMethod();
                    obj.sum += val;
                }

Вот результаты теста по нескольким вариантам

Свойство 'o.sum' и BaseClass с BaseClass.Counter++
342.70000000298023
Переменная 'sum' и BaseClass с BaseClass.Counter++
406.09999999403954

Свойство 'o.sum' и ConstClass с ConstClass.Counter++
179.20000000298023
Переменная 'sum' и ConstClass с ConstClass.Counter++
90

Свойство 'o.sum' и this.constructor.Counter++
183.09999999403954
Переменная 'sum' и this.constructor.Counter++
84.59999999403954

Свойство 'o.sum' и prototype
178.80000001192093
Переменная 'sum' и prototype
84.40000000596046


  сам скрипт тестирования
    const TestsNumber = 1;
    const ItemsNumber = 100_000_000;

    function Test(func) {
        let totalTime = 0;

        for (let i = 0; i < TestsNumber; i++) {
            let watch = performance.now();

            func();

            let curTime = performance.now() - watch;
            totalTime += curTime;
        }

        console.log(totalTime / TestsNumber);
    }
    
    // BaseClass.Counter++
    class BaseClass
    {
        TestMethod() {
            this.Value = BaseClass.Counter++;
            return this.Value;
        }

        static Counter = 0;
    }


    console.log("Свойство 'o.sum' и BaseClass с BaseClass.Counter++");
    Test(function() {
        let o = { sum: 0 };

        for (let i = 0; i < ItemsNumber; i++) {
            let obj = new BaseClass();
            let val = obj.TestMethod();
            o.sum += val;
        }
    });

    console.log("Переменная 'sum' и BaseClass с BaseClass.Counter++");
    BaseClass.Counter = 0;
    Test(function() {
        let sum = 0;
        
        for (let i = 0; i < ItemsNumber; i++) {
            let obj = new BaseClass();
            let val = obj.TestMethod();
            sum += val;
        }
    });
    
    // const class
    const ConstClass = class
    {
        TestMethod() {
            this.Value = ConstClass.Counter++;
            return this.Value;
        }

        static Counter = 0;
    }
    
    console.log("\nСвойство 'o.sum' и ConstClass с ConstClass.Counter++");
    Test(function() {
        let o = { sum: 0 };

        for (let i = 0; i < ItemsNumber; i++) {
            let obj = new ConstClass();
            let val = obj.TestMethod();
            o.sum += val;
        }
    });

    console.log("Переменная 'sum' и ConstClass с ConstClass.Counter++");
    ConstClass.Counter = 0;
    Test(function() {
        let sum = 0;
        
        for (let i = 0; i < ItemsNumber; i++) {
            let obj = new ConstClass();
            let val = obj.TestMethod();
            sum += val;
        }
    });

    // через this.constructor.Counter
    class BaseClass2
    {
        TestMethod() {
            this.Value = this.constructor.Counter++;
            return this.Value;
        }

        static Counter = 0;
    }

    console.log("\nСвойство 'o.sum' и this.constructor.Counter++")
    Test(function() {
        let o = { sum: 0 };

        for (let i = 0; i < ItemsNumber; i++) {
            let obj = new BaseClass2();
            let val = obj.TestMethod();
            o.sum += val;
        }
    });

    console.log("Переменная 'sum' и this.constructor.Counter++")
    BaseClass2.Counter = 0;
    Test(function() {
        let sum = 0;
        
        for (let i = 0; i < ItemsNumber; i++) {
            let obj = new BaseClass2();
            let val = obj.TestMethod();
            sum += val;
        }
    });
    
    // По-старинке
    class ProtoClass
    {
        TestMethod() {
            this.Value = Object.getPrototypeOf(this).Counter++;
            return this.Value;
        }
    }
    ProtoClass.prototype.Counter = 0;

    console.log("\nСвойство 'o.sum' и prototype");
    Test(function() {
        let o = { sum: 0 };

        for (let i = 0; i < ItemsNumber; i++) {
            let obj = new ProtoClass();
            let val = obj.TestMethod();
            o.sum += val;
        }
    });

    console.log("Переменная 'sum' и prototype");
    ProtoClass.prototype.Counter = 0;
    Test(function() {
        let sum = 0;
        
        for (let i = 0; i < ItemsNumber; i++) {
            let obj = new ProtoClass();
            let val = obj.TestMethod();
            sum += val;
        }
    });
Re[23]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 13.06.24 01:56
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>У тебя ошибка — внешний obj не используется, вместо него внутри цикла ты пишешь значение в только что созданный объект


Да, есть такое дело. Но по скорости пофиг:

336.42000000029805
1444.9300000000744

        let func = function()
        {
            let sum = 0;
            
            for (let i = 0; i < ItemsNumber; i++)
            {
                let obj = new BaseClass();
                let val = obj.TestMethod();
                sum += val;
            }
        };

        Test(func);
        Test(func);
Ад пуст, все бесы здесь.
Re[21]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 13.06.24 06:50
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Только в хроме, в фаерфоксе такого эффекта нет.


Фаерфокс у меня вообще ничего не выводит
Re[22]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 13.06.24 17:55
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Фаерфокс у меня вообще ничего не выводит


А в Хроме?
Ад пуст, все бесы здесь.
Re[23]: JS. Откуда такая разница в скорости?
От: rFLY  
Дата: 13.06.24 18:13
Оценка:
Здравствуйте, Codealot, Вы писали:

C>А в Хроме?

Ты проставил TestsNumber = 10 так что Pauel мог и не дождаться, я менял на 1 чтобы посмотреть
Re[24]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 13.06.24 19:33
Оценка:
Здравствуйте, rFLY, Вы писали:

FLY>Ты проставил TestsNumber = 10 так что Pauel мог и не дождаться, я менял на 1 чтобы посмотреть


Всего 15-20 секунд, обычный вебсайт часто грузится дольше.
При 1 такого эффекта почему-то нет
Ад пуст, все бесы здесь.
Re[23]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.06.24 12:05
Оценка:
Здравствуйте, Codealot, Вы писали:

P>>Фаерфокс у меня вообще ничего не выводит


C>А в Хроме?


Нет разницы с тем что вы и rfly здесь показываkb
Re: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.06.24 12:08
Оценка:
Здравствуйте, Codealot, Вы писали:

C>Запускаю код в хроме.


Если вам интересны всякие такие вещи, вы можете глянуть на so поиском по 'V8 developer here', https://stackoverflow.com/search?q=V8+developer+here

У меня в свое время было пару странностей в перформансе, и на so товарищ из v8 все объяснил.
Re[24]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 18.06.24 14:53
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Нет разницы с тем что вы и rfly здесь показываkb


Так есть разница между первым и вторым вызовом или нет?
Ад пуст, все бесы здесь.
Re[25]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 18.06.24 17:27
Оценка:
Здравствуйте, Codealot, Вы писали:

P>>Нет разницы с тем что вы и rfly здесь показываkb


C>Так есть разница между первым и вторым вызовом или нет?


Есть, всё так же как у вас с rfly. Он вам и объяснил, в чем дело.
Re[26]: JS. Откуда такая разница в скорости?
От: Codealot Земля  
Дата: 18.06.24 19:45
Оценка:
Здравствуйте, Pauel, Вы писали:

P>Есть, всё так же как у вас с rfly. Он вам и объяснил, в чем дело.


Там еще другой случай.
Ад пуст, все бесы здесь.
Re[27]: JS. Откуда такая разница в скорости?
От: Pauel Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.06.24 08:28
Оценка:
Здравствуйте, Codealot, Вы писали:

P>>Есть, всё так же как у вас с rfly. Он вам и объяснил, в чем дело.


C>Там еще другой случай.


https://stackoverflow.com/search?q=V8+developer+here
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.