V8 TypedArray производительность скалы, когда проверка границ устранена? - PullRequest
0 голосов
/ 14 октября 2018

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

function fill(buf, from, to, val) {
    for (var i = from; i < to; ++i)
        buf[i] = val;
}

Функция вызывается только с одним типом массива, а остальные параметры всегда находятся в границах.Один только этот код работает аналогично коду C, с несколькими 100 миллионами обращений к массиву в секунду, и все хорошо.Как и ожидалось, TurboFan вводит проверки границ, чтобы убедиться, что индекс остается в допустимом диапазоне.

Но когда я явно добавляю эти проверки границ в функцию:

function fill(buf, from, to, val) {
    if (from < 0 || to < from || buf.length < to)
        throw new Error();
    for (var i = from; i < to; ++i)
        buf[i] = val;
}

запись в массив неожиданно завершаетсяс общим ключом KEYED_STORE_IC, замедляющим выполнение в 50 .

режиме, это мой тестовый набор (1 миллион вызовов, ~ 4 миллиарда записей):

var b = new Int32Array(10000);
for (var j = 0; j < 999999; ++j) {
    fill(b, j & 0xFFF, 6000 + (j % 0xFF), j);
}

Библиотека должна работать достаточно хорошо во всех браузерах и на узле 8.x / 10.x.Тест был выполнен с v8.10 (V8 версия 6.2.414.50).

1 Ответ

0 голосов
/ 15 октября 2018

V8 разработчик здесь.Как вы измерили эту разницу?Я не могу воспроизвести его.

Я скопировал ваш код в squarefree.com/shell/shell.html, по модулю переименовав одну из функций:

function fill(buf, from, to, val) {
    for (var i = from; i < to; ++i)
        buf[i] = val;
}
function fill2(buf, from, to, val) {
    if (from < 0 || to < from || buf.length < to)
        throw new Error();
    for (var i = from; i < to; ++i)
        buf[i] = val;
}
var b = new Int32Array(10000);
var t1 = Date.now();
for (var j = 0; j < 999999; ++j) {
    fill(b, j & 0xFFF, 6000 + (j % 0xFF), j);
}
var t2 = Date.now();
for (var j = 0; j < 999999; ++j) {
    fill2(b, j & 0xFFF, 6000 + (j % 0xFF), j);
}
var t3 = Date.now();

После выполнения этого (текущий Chrome Canary), Я получаю:

> t2 - t1
< 5820
> t3 - t2
< 5887

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

Я полагаю, что у вас временно была ошибка в вычислениях индекса ив конечном итоге получил за пределами доступа.Это объясняет, почему использовалась общая микросхема, и почему вы наблюдали значительное замедление.

...