Re[83]: Реальная производительность WebAssembly?
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 04.11.17 09:53
Оценка: :)
Здравствуйте, CoderMonkey, Вы писали:

I>>Какой рантайм — экспериментальный, ближе всего к нему будет наверное node 8.8.1 64, точнее не могу сказать. На самом деле уже не важно. И вот почему — я позапускал эту версию от 19го сентября на разных компах с разной производительностью и сортировка везде укладывается в 1600+- 200 мс.


CM>Надо же, какой магический рантайм. Скорость от железа вообще не зависит.


Правильно так — зависит не от абстрактного "железа", а от пропускной способности шины/памяти, о чем уже много раз говорилось. Ты наверняка сам собирал себе комп, раз "сэкономил" для такого процессора на хилой памяти. Ну может такой же "умелец" собирал конфигурацию.

Будешь смеяться, у тебя DDR3 и именно это объясняет эти полторы секунды. Почему в C# меньше — потому что C# не забивает шину лишними обращениями, в ём тупо косвенность раза в полтора-два ниже.
Именно отсюда получается результат 1600+- 200. Проц и кеш и определяют эти +-200мс тупо потому, что они намного быстрее узкого места — шины/памяти.

CM>Хотя нет, я в магию не верю. Так что вся магия наверняка заключается в каком-то очень особом способе измерения.


Смотри внимательно подчеркнутую часть:

— если сравнить версии нода от 6й до 9й, то внезапно окажется, что где то посередине перформанс _падает_ на сортировке, при чем значительно, около 15%.
— на имеющемся железе(разные компы) сортировка работает в районе 1600+-200мс. А вот инициализация от 2500 до 6500мс. node 8.8.1 64

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

Теперь очередная попа-боль для тебя: http://rsdn.org/forum/flame.comp/6947971.1
Автор: Ikemefula
Дата: 28.10.17

Замеры видишь ? Я их сюда скопирую, на всякий, если у тебя со зрением проблемы:
Init, miliseconds: 1598
Sort miliseconds: 1573


  Энергичная версия JS, длинные числа вместо GUID
'use strict';

const N = 1000*1000;
const re = /-/g;
const arr = Array(N);

function Main(number) {
    let watch = Date.now();
    let vals = arr; 
    
    for(let i = 0; i<arr.length; i++) {
        arr[i] = new TestClass();
    }
    
    let compare = (x, y) =>{
        if(x === y)
            return 0;
        if(x > y)
            return 1;
        return -1;
    };
    console.warn(`Init, miliseconds: ${Date.now() - watch}`);
    
    watch = Date.now();
    QuickSort(vals, (x,y)=>compare(x.Id, y.Id));
    console.warn(`Sort miliseconds: ${Date.now() - watch}`);
}

function QuickSort(vals, compare){
    QuickSortImpl(vals, compare, 0, vals.length - 1);
}

function QuickSortImpl (vals, compare, left, right) {
    if (right <= left)
        return;

    let i = left;
    let j = right;
    const mid = Math.floor((left + right) / 2);
    const midVal = vals[mid];

    while (i <= j) {
        while (compare(vals[i], midVal) > 0) {
            i++;
        }

        while (compare(vals[j], midVal) < 0) {
            j--;
        }

        if (i <= j) {
            const tmp = vals[i];
            vals[i] = vals[j];
            vals[j] = tmp;

            i++;
            j--;
        }
    }

    if(left < i - 1) {
        QuickSortImpl(vals, compare, left, i - 1);
    }

    if(right > i) {
        QuickSortImpl(vals, compare, i, right);
    }
}

class TestClass {
    constructor() {
        this.Id = CreateGuid();
        this.Value = CreateGuid();
    }

    toString() {
        return this.Id;
    }
}

function ToArray(iterator) {
    return [...iterator];
}

function* Range(start, end) {
    for(let i = start; i<end; i++) {
        yield i;
    }
}

function* Select(iterator, projector) {
    for(let x of iterator) {
        yield projector(x);
    }
}

function CreateGuid() {
    let num = 0|Math.random() * Math.pow(10, 16);

    return num.toString(16);
    //return NewGuid().toString().replace(re, "");
}

function NewGuid() {
    function s4() {
        return (((1 + Math.random()) * 0x10000) & 0xFFFF).toString(16);
    }
    return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
        s4() + '-' + s4() + s4() + s4();
}

function delay(time) {
    return new Promise((resolve)=>{
        setTimeout(resolve, time);
    });
}

for(let i = 0, promise = Promise.resolve(); i<100;i++) {
    promise = promise.then(()=>Main(N)).then(()=>delay(1000));
}


Здесь наблюдаем ровно ту же магию — сортировка каким то чудом держится в районе той же магической границы 1600+-200.

Вот еще два замера на том же хилом железе:
Init, miliseconds: 1163
Sort miliseconds: 1654

Init, miliseconds: 1306
Sort miliseconds: 1836


I>>Более того — даже разные рантаймы дают очень похожее число, колебания в пределах 15%.

CM>Разброс даже на том же самом железе и той же версии рантайма +-25%.

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

I>>Если мы про алгоритмы, то их принято доказывать, что они являются тем, что надо

CM>Элементарно, если тебе яйца танцевать мешают или еще какие проблемы подобного характера.
CM>Из 300 случайных тестовых наборов по миллиону записей, ноль ошибок. А теперь, вероятно, ты опять начнешь юлить и выкручиваться?

Хоть миллиард тестов по миллиону. Нужно доказать общий случай, а миллион — это ровно один. Студенты часто делают сорировку, которая работает, скажем, для четных или для тех, что делятся на 4 и тд.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.