Re[26]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 16.01.14 10:33
Оценка:
Здравствуйте, smeeld, Вы писали:

S>boost::asio и на тестах через внутренний интерфейс сливает релизации на чистом C API.

пример-то есть?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[26]: асинхронная сериализация
От: andrew.f  
Дата: 21.01.14 10:24
Оценка: 12 (1) +1
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, andrew.f, Вы писали:


AF>>Или Вы серьезно не умеете оптимизировать под разные типы системных вызовов?

X>где в моем примере использование системных вызовов? или ты таки считаешь, что printf() это системный вызов?

Хорошо, понял что в этом месте у тебя белое пятно, потому просвещаю.
Следующий код:
std::cout << "Hello " << 10 << " world" << std::endl;


В виде машиного кода — это серия call по разным адресам. Замечательно то, что адреса фиксированные, а не грузятся из некой таблицы.

Следующий код:
printf("%s %d %s\n", "Hello", 10, "world");


Это один call, внутри которого пробег по массиву (замечательно оптимизируется загрузкой в кеш процессора) + switch (тоже замечательно оптимизируется.

Сравниваем оба варианта. При увеличении количества параметров std::cout увеличивает количество call. А printf — push в стек. Тут есть какие нибудь непонятки?

По аналогии select vs poll. select — серия системных вызовов. poll — один системный вызов с большим массивом входных данных. Потому poll работает лучше — меньше переключений. Потому printf с кучей параметров работает лучше std::cout — меньше сбрасывания кеша процессора.

Теперь смотрим на твой тест, который и для std::cout и для printf делается тоже самое — вызывает функцию с одним параметром.
НО, в случае std::cout — это call в функцию, в которой не делается ничего лишнего, только конкретный тип параметра преобразуется в строчку.
А в случае printf — это call в функцию, в которой делается switch, чтобы преобразовать конкретный тип параметра в строчку.

Естественно, printf в твоем примере проиграет. Но зная теперь как это устроенно внутри, ты сможешь написать тест, в котором printf таки обгонит std::cout? Или все равно не сможешь?
Re[24]: асинхронная сериализация
От: VladFein США  
Дата: 21.01.14 19:29
Оценка:
Здравствуйте, niXman, Вы писали:

X>что за бред?!

X>с каких таких пор эта сишная всезаглатывающая кишка стала быстрее плюсовых потоков?!
  Скрытый текст
X>

X>#include <cstdio>
X>#include <iostream>
X>#include <chrono>

X>enum io_type { test_printf, test_stdio };

X>template<io_type>
X>struct test;

X>template<>
X>struct test<test_printf> {
X>    template<typename T>
X>    static std::chrono::milliseconds
X>    run(const T *arr, std::size_t size) {
X>        auto start = std::chrono::system_clock::now();
X>        for ( ; size; --size ) {
X>            printf("%d", *arr++);
X>        }
X>        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()-start);
X>    }
X>};

X>template<>
X>struct test<test_stdio> {
X>    template<typename T>
X>    static std::chrono::milliseconds
X>    run(const T *arr, std::size_t size) {
X>        auto start = std::chrono::system_clock::now();
X>        for ( ; size; --size ) {
X>            std::cout << *arr++;
X>        }
X>        return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()-start);
X>    }
X>};

X>int main() {
X>    enum { size = 1024*1024*4 };
X>    int *ia = new int[size];
X>    auto t1 = test<test_printf>::run(ia, size);
X>    std::cerr << "printf time =" << t1.count() << std::endl;
X>    auto t2 = test<test_stdio >::run(ia, size);
X>    std::cerr << "stdio  time =" << t2.count() << std::endl;
X>}

X>

X>запускаем:
X>

X>./iospeed 1>/dev/null

X>получаем:
X>

X>printf time =323
X>stdio time =183


X>да и как вообще может быть такое, чтоб printf() который вообще ничего не знает о типе, выполнялся быстрее типизированного кода?

Можно я немножко разобью эту теорию?
Поменяйте местами вызовы тестов и результат будет противоположным.

stdio time =308395
printf time =266533

Надо объяснить — почему?
Re[27]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.01.14 19:44
Оценка:
Здравствуйте, andrew.f, Вы писали:

ну и зачем ты "это" тут оставил? разве я спрашивал как работает std::cout или printf() ?
если ты так и не понял мой посыл, то он состоял только в том — что мне плевать на потроха printf(), и в том, что std::cout имеет больше шансов на успешную оптимизацию и более типобезопасен.
но что я понял, так это то, что ты предлагаешь вместо std::cout юзать *надцать перегрузок рукоблудного printf(). но нет, спасибо, это не мой путь.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[27]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.01.14 19:46
Оценка:
Здравствуйте, andrew.f, Вы писали:

AF>По аналогии select vs poll. select — серия системных вызовов. poll — один системный вызов с большим массивом входных данных.

т.е. в твоей реальности, select() мониторит только один дескриптор? (страшно жить)
и да, плюс poll() не в этом.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[25]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.01.14 20:08
Оценка:
Здравствуйте, VladFein, Вы писали:

VF>Поменяйте местами вызовы тестов и результат будет противоположным.

VF>Надо объяснить — почему?
ничего не изменилось. нужно объяснять, почему?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[26]: асинхронная сериализация
От: VladFein США  
Дата: 21.01.14 20:29
Оценка:
Здравствуйте, niXman, Вы писали:

VF>>Поменяйте местами вызовы тестов и результат будет противоположным.

VF>>Надо объяснить — почему?
X>ничего не изменилось.

А новый результат можно посмотреть?

X>нужно объяснять, почему?


Потому, что только что прочитанные данные второй раз читаются быстрее.
Re[27]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.01.14 20:50
Оценка:
Здравствуйте, VladFein, Вы писали:

VF>А новый результат можно посмотреть?

niXman@niXman-pc ~/tests
$ ./stdio 1>/dev/null
printf time =31600
stdio time =18979

niXman@niXman-pc ~/tests
$ ./stdio 1>/dev/null
stdio time =18801
printf time =31898

пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[26]: асинхронная сериализация
От: VladFein США  
Дата: 21.01.14 21:03
Оценка:
Здравствуйте, niXman, Вы писали:

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


VF>>Поменяйте местами вызовы тестов и результат будет противоположным.

VF>>Надо объяснить — почему?
X>ничего не изменилось. нужно объяснять, почему?

Кстати, а зачем измерять время организации цикла и доступа к куче памяти?
Предлагаю другой тест:

#include <windows.h>
#include <stdio.h>
#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    ULONG64 ct1(0), ct2(0);
    HANDLE ht = GetCurrentThread();
    float f = argc*3.333;
    QueryThreadCycleTime(ht, &ct1);
    printf("%d\n", argc);
    QueryThreadCycleTime(ht, &ct2);
    cout << "printf: " << ct2 - ct1 << endl;
    QueryThreadCycleTime(ht, &ct1);
    cout << argc << endl;
    QueryThreadCycleTime(ht, &ct2);
    cout << "cout  : " << ct2 - ct1 << endl;
    return 0;
}


Этот тест показывает очень маленькое преимущество cout над printf:

1
printf: 151106
1
cout : 132460
Press any key to continue . . .


Но давайте добавим всего по два параметра и сравним:
#include <windows.h>
#include <stdio.h>
#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    ULONG64 ct1(0), ct2(0);
    HANDLE ht = GetCurrentThread();
    float f = argc*3.333;
    QueryThreadCycleTime(ht, &ct1);
    printf("%d %f %s\n", argc, f, argv[0]);
    QueryThreadCycleTime(ht, &ct2);
    cout << "printf: " << ct2 - ct1 << endl;
    QueryThreadCycleTime(ht, &ct1);
    cout << argc << " " << f << " " << argv[0] << endl;
    QueryThreadCycleTime(ht, &ct2);
    cout << "cout  : " << ct2 - ct1 << endl;
    return 0;
}

1 3.333000 D:\Code\2010\ConsoleTest\Release\ConsoleTest.exe
printf: 193920
1 3.333 D:\Code\2010\ConsoleTest\Release\ConsoleTest.exe
cout : 1875342
Press any key to continue . . .

printf выигрывает в 10 (десять!) раз.

А у вас? Опять никакой разницы???
Re[27]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.01.14 21:29
Оценка:
Здравствуйте, VladFein, Вы писали:

три момента:
1. где мне взять вендус?
2. не очень понимаю, как работает этот тест, и что он тестирует. чем предыдущий тест плох? замеряет то, что не нужно? — так и должно быть, мы меряем штатное использование, а не синтетическое
3. ты и andrew.f, похоже совсем не в курсе, как работают стандартные потоки
так уж и быть, объясню: дело в том, что манипулятор std::endl выполняет бОльшую работу, которую символ '\n' используемый для printf() — не выполняет.
в моем тесте именно по этому нет ни первого, ни второго.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[28]: асинхронная сериализация
От: VladFein США  
Дата: 21.01.14 22:23
Оценка:
Здравствуйте, niXman, Вы писали:

X>три момента:

X>1. где мне взять вендус?
а чем на никсах меряют время когда не хотят 4 млн. циклов?

X>2. не очень понимаю, как работает этот тест, и что он тестирует. чем предыдущий тест плох? замеряет то, что не нужно? — так и должно быть, мы меряем штатное использование, а не синтетическое

Мой тест меряет время исполнения ОДНОГО вызова, в процессорных циклах. При чём здесь "синтетическое" использование? А "штатное", по-твоему, это замер всякого мусора?

X>3. ты и andrew.f, похоже совсем не в курсе, как работают стандартные потоки

X> так уж и быть, объясню: дело в том, что манипулятор std::endl выполняет бОльшую работу, которую символ '\n' используемый для printf() — не выполняет.
X> в моем тесте именно по этому нет ни первого, ни второго.
А я (не скажу за andrew.f) и не интересуюсь тем, КАК они работают.
После того, как я убрал std::endl (который в реальной жизни очень часто встречается), результат изменился не существенно:

1 3.333000 D:\Code\2010\ConsoleTest\Release\ConsoleTest.exeprintf: 176648
1 3.333 D:\Code\2010\ConsoleTest\Release\ConsoleTest.execout : 1816776
Press any key to continue . . .


ну и?
Re[28]: асинхронная сериализация
От: andrew.f  
Дата: 24.01.14 02:51
Оценка: -2
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, andrew.f, Вы писали:


X>ну и зачем ты "это" тут оставил? разве я спрашивал как работает std::cout или printf() ?


Не спрашивал, но судя по коду, приведенного теста, ты просто не в курсе, как оно внутри устроенно, потому и оставил...

X>если ты так и не понял мой посыл, то он состоял только в том — что мне плевать на потроха printf(), и в том, что std::cout имеет больше шансов на успешную оптимизацию и более типобезопасен.


"Типобезопасен" — да, "имеет больше шансов на успешную оптимизацию" — нет.
Либо одно, либо другое...
Надо смотреть на задачу, иногда то небольшое проседание, которое дают STL потоки, бывает критичным.

X>но что я понял, так это то, что ты предлагаешь вместо std::cout юзать *надцать перегрузок рукоблудного printf(). но нет, спасибо, это не мой путь.


Не предлагаю — STL потоки удобнее.
Первоначальный посыл был, что C++-код оптимизируется лучше, в качестве примера был приведен qsort vs std::sort (либо другое по-вкусу).
Только — это пример притянутый за уши...
Re[28]: асинхронная сериализация
От: andrew.f  
Дата: 24.01.14 03:18
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, andrew.f, Вы писали:


AF>>По аналогии select vs poll. select — серия системных вызовов. poll — один системный вызов с большим массивом входных данных.

X>т.е. в твоей реальности, select() мониторит только один дескриптор? (страшно жить)
X>и да, плюс poll() не в этом.
Что то аж лень писать, как и тебе впрочем.... Каждый о своем, а в результате спор ни о чем....

Нет не на один — select завязан на значение FD_SETSIZE.
И да я в курсе, что select иногда работает быстрее epoll...
И синхронное API скорострельнее ассинхронного ....
Ну и про остальное тоже ....

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