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

конструктора нет
Ад пуст, все бесы здесь.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.