Как бы я переписал операторы for в этой функции, чтобы они были более производительными?

#javascript #performance #for-loop #optimization #micro-optimization

Вопрос:

У меня есть следующая функция:

 ColorPalette._processPaletteImageData = function() {
    const paletteImage = this._bmp();
    const source = this._source;
    if (paletteImage) {
        const _colorPicker = (_n) => {
            const pX = source.offsetX   (_n % 8) * 12   6;
            const pY = source.offsetY   Math.floor(_n / 8) * 12   6;
            return paletteImage.getPixel(pX, pY);
        };
        const _toRgba = (_o) => {return [_o.r, _o.g, _o.b, _o.a]};
        const dataDivisions = source.dataDivisions;
        const splits = (dataDivisions.length - 1);
        let tally = 0;
        for (let i = 0; i <= splits; i  ) {
            this._data[i] = {};
            const colors = (dataDivisions[i] - 1);
            for (let j = 0; j <= colors; j  ) {
                const position = tally   j;
                const hex = _colorPicker(position);
                const color = tinycolor(hex);
                const rgba = _toRgba(color.toRgb());
                const score = Utils.computeColorScore(rgba);
                const [colorName, shade] = Utils.hexToColorName(hex).split(DIVISION);
                const inverse = Utils.invertColor(hex, false);
                const complement = color.complement().toHexString();
                this._data[i][colorName] = {
                    "hex": hex,
                    "compliment": complement,
                    "inverse": inverse,
                    "rgba": rgba,
                    "score": score,
                    "shade": shade,
                };
            };
            tally  = colors   1;
        };
    };
};
 

В вышеупомянутом коде есть два оператора for:

  1. for (let i = 0; i <= splits; i )
  2. for (let j = 0; j <= colors; j )

Как бы я переписал функцию так, чтобы операторы For выглядели так:

  1. for (let i = splits; i >= 0; i--)
  2. for (let j = colors; j >= 0; j--)

Комментарии:

1. Ваш код в настоящее время работает так, как ожидалось? Почему вы думаете, что инвертирование порядка циклов улучшит производительность?

2. Кроме того, чтобы помочь вам оптимизировать свой код, было бы полезно понять, что вы пытаетесь сделать в первую очередь.

3. @ErnestoStifano: Предположительно, потому что при переходе на машинный код x86 он может компилироваться в dec reg / jge / / вместо inc reg / cmp reg,reg / jle , сохраняя инструкцию (и на процессорах , отличных от AMD, uop для интерфейса) и, возможно, освобождая регистр, которому не нужно удерживать привязку цикла. IDK, будут ли текущие компиляторы JS JIT создавать более приятные циклы для менее идиоматичного источника или нет. Однако при использовании i или j индексировании памяти несколько худшая аппаратная предварительная выборка для зацикливания в порядке уменьшения адресов может быть большим фактором.

4. (Очевидно, не стоит усложнять тело цикла только для того, чтобы включить другое управление циклом, это приведет к небольшой экономии, поэтому, если есть какая-либо зависимость между итерациями или причина для выполнения цикла в прямом порядке, просто сделайте это.)

5. @PeterCordes спасибо, что указали на это, это очень интересно. Я особенно согласен с вашим последним комментарием. Особенно если мы рассмотрим современные движки ECMAScript, оптимизация которых сильно динамична и не обязательно включает в себя прямой этап компиляции JIT для машинного кода. Любой код, выполняемый внутри цикла, скорее всего, повлияет на производительность гораздо сильнее, чем сама структура цикла.