Re[9]: асинхронная сериализация
От: smeeld  
Дата: 28.12.13 22:40
Оценка: -1 :)
Здравствуйте, Abyx, Вы писали:

A>почему *желательно*, обоснуйте.

Можно задать встречный вопрос?
Вы смотрели на ассемблерные листинги программ на C++ и C?
Если тот кошмар, который генерит компилятор с C++ по сравнению с тем, что получается с C подобного синтаксиса
способствует снижению латентности,
то этот мир не совершенен больше, чем предпологалось.
Re[10]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 28.12.13 23:19
Оценка: +1
Здравствуйте, smeeld, Вы писали:

S>Вы смотрели на ассемблерные листинги программ на C++ и C?

я — смотрел. и да, С++ компилятор генерит более качественный код, и оптимизирует лучше.
а что я, по вашему, должен был там еще увидеть?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[10]: асинхронная сериализация
От: Abyx Россия  
Дата: 28.12.13 23:20
Оценка:
Здравствуйте, smeeld, Вы писали:

A>>почему *желательно*, обоснуйте.

S>Можно задать встречный вопрос?
S>Вы смотрели на ассемблерные листинги программ на C++ и C?
да, приходилось когда занимался реверсированием.
однако на асм своего кода обычно смотреть не нужно, С и С++ довольно просто компилируются в уме.

S>Если тот кошмар, который генерит компилятор с C++ по сравнению с тем, что получается с C подобного синтаксиса

S>способствует снижению латентности,
S> то этот мир не совершенен больше, чем предпологалось.
согласен, особенно страшный код генерится из Boost.MPL — шаблонные меташтуки, это же квинтэссенция С++, правда?

может Вы поделитесь с нами какими-то конкретными примерами? типа "вот код с одинаковой функциональностью и одинаковыми свойствами, у С++ кода такой результат компиляции, а у С — лучше"
In Zen We Trust
Re[10]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 28.12.13 23:20
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Ну, new не критичен, можно и оставить.

чем вы руководствуетесь, принимая подобные решения?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: асинхронная сериализация
От: Abyx Россия  
Дата: 28.12.13 23:24
Оценка: 6 (1)
Здравствуйте, Lazin, Вы писали:

L>Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>>Собственно у меня два вопроса:

EP>>1. Какие есть ещё альтернативы? Возможно есть какие-то стандартные/распространённые решения?
L>JSON

в JSON нет типизации, поэтому для де-сериализации полиморфных типов нужен промежуточный этап парсинга в DOM,
тогда как форматы поддерживающие типизацию (например yaml) позволяют использовать потоковый парсер (типа как SAX)
In Zen We Trust
Re[10]: асинхронная сериализация
От: Evgeny.Panasyuk Россия  
Дата: 29.12.13 07:12
Оценка:
Здравствуйте, niXman, Вы писали:

EP>>В данном случае для сериализации нужны только правильные архивы, которые в любом случае писать — что для YAS, что для Boost.Serialization.

X>что это значит?

Данные должны быть в строго определённом формате, с правильным порядком байт.

EP>>рекурсивная сериализация Boost.Fusion Forward Sequence.

X>YAS это умеет искаропки.

Я видел. У меня это меньше 15 строк. Там считай только один вызов fusion::for_each или fusion::fold.
Re[2]: асинхронная сериализация
От: Evgeny.Panasyuk Россия  
Дата: 29.12.13 07:24
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Вторая задача решается довольно просто, если у вас есть некий итератор по этой древовидной структуре, который умеет по запросу выдавать следующий элемент. Тогда вы просто, по мере готовности сокета, обходите свою структуру с помощью этого итератора, и по кусочкам проталкиваете в сеть.


Так вопрос как раз в том, как этот итератор для древовидной структуры сделать. Учитывая то, что узлы структуры гетерогенные.

Pzz>Что до первой задачи, вы слишком мало рассказали про свою структуру, чтобы к ней хоть как-то отнестись.


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

Pzz>Да, и учтите пожалуйста, что зачастую выгоднее потратить пару мегабайт памяти, чем изобретать хитроумные алгоритмы, позволяющие этого не делать.


Соединений десятки тысяч. Буфер для одного соединения может занимать до нескольких мегабайт. В среднем случае экономия порядка гигабайт.

Pzz>Объем памяти (в разумных, конечно, пределах) — гораздо более дешевый ресурс, чем производительность процессора.


"Да и вообще всё базу упирается!"

Если серьёзно, то в общем случае при меньшем использовании памяти:
1. есть возможность полностью поместится в L3, что является огромным boost'ом для производительности.
2. меньше вероятность cache miss
3. свободную память можно использовать для разного рода кэшей, а-ля memcached, или кэш самой OS
4. свободную память можно использовать для space–time tradeoff — например отдавать хэштаблицам много места, чтобы реже получать коллизии.
Re[8]: асинхронная сериализация
От: Evgeny.Panasyuk Россия  
Дата: 29.12.13 07:33
Оценка:
Здравствуйте, smeeld, Вы писали:

S>а вот для организации ввода/вывода не прозрачней будет вместо boost::asio использовать, например, в линуксе нативный epoll?


Что это даст?

S>Сама boost::asio, та её часть, что относится к асинхронному вводу/выводу есть обёртка над epoll в линуксе.

S>Понятно, что потеряется кроссплатформенность, но при использование простого api epoll проще будет реализовать
S>сложную логику последовательной, растянутой во времени передачи сериализованных данных частями в несколько
S>тысяч потоков чем эти async_read/async_write которые обязательно поведут себя неизветно как.

С async_read/async_write нет никаких проблем — всё удобно и прозрачно. Проблемы начнутся если без нужды вручную использовать epoll.
К тому же в контексте асинхронной сериализации, epoll не добавляет ничего что помогло бы решить проблему.

EP>>Соединений десятки тысяч. Десятки тысяч потоков/процессов не взлетят.

S>Есть спасение, берём четырёхпроцовый сервак, несколко, с балансировкой между ними.

Зачем, если и так всё прекрасно работает?

S>А как тогда взлетают веб сервисы? Асинхронная обработка в один поток годится только если, собственно,

S>обработки не много. В противном случае пускаем новый поток/процесс. Связки однопоточный nginx в frontend для распределения запросов и многопроцессный apache для обработки запросов в backend-стандарт для hayload.

Смотрим на node.js, erlang, да и вообще общий тренд к использованию зелёных потоков.

EP>>Asio не принципиально — подойдёт любой асинхронный/неблокирующий вывод — и везде будут ровно те же проблемы.

S>Вот и я о том же, используем более предсказуемые нативные для ОС api kqueue (freebsd), epoll (linux), не знаю
S>что там есть по этому поводу в win.

Переход на ручной epoll не решит никаких проблем с асинхронной сериализацией.
Re[10]: асинхронная сериализация
От: Evgeny.Panasyuk Россия  
Дата: 29.12.13 07:41
Оценка:
Здравствуйте, smeeld, Вы писали:

A>>почему *желательно*, обоснуйте.

S>Можно задать встречный вопрос?
S>Вы смотрели на ассемблерные листинги программ на C++ и C?
S>Если тот кошмар, который генерит компилятор с C++ по сравнению с тем, что получается с C подобного синтаксиса
S>способствует снижению латентности,
S> то этот мир не совершенен больше, чем предпологалось.

Я провёл сотни часов смотря на том что генерирует компилятор. И в контексте RE, и в контексте оптимизации.
C++ позволяет компиляторам генерировать намного более быстрый код чем C. Хотя бы потому, что язык не выбрасывает всю полезную информацию так необходимую для оптимизации.

Классический пример — std::sort vs qsort. Какой интерфейс более простой, гибкий, и позволяет генерировать оптимальный код?

P.S. Это уже offtopic, лучше перейти в другую тему. Тем более сто раз уже разжёвывалось.
Re[3]: асинхронная сериализация
От: Pzz Россия https://github.com/alexpevzner
Дата: 29.12.13 17:51
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

Pzz>>Вторая задача решается довольно просто, если у вас есть некий итератор по этой древовидной структуре, который умеет по запросу выдавать следующий элемент. Тогда вы просто, по мере готовности сокета, обходите свою структуру с помощью этого итератора, и по кусочкам проталкиваете в сеть.


EP>Так вопрос как раз в том, как этот итератор для древовидной структуры сделать. Учитывая то, что узлы структуры гетерогенные.


Ну, если представить себе, что узлы структуры состоят из каких-то собственных данных и ссылок на подузлы, добавляем ссылку назад и храним в итераторе текущий узел, номер текущей ссылки на подузел и, если собственные данные достаточно большие, текущее положение в них.

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

EP>Если серьёзно, то в общем случае при меньшем использовании памяти:

EP>1. есть возможность полностью поместится в L3, что является огромным boost'ом для производительности.

Скорее всего, вы на этом мало чего наиграете. Эта память, в которую вы один раз кладете, и один раз забираете. Причем забираете со скоростью сокета, т.е., весьма неторопясь. Пока за данными придут, из кэша они давно уже вылетят.

EP>2. меньше вероятность cache miss

EP>3. свободную память можно использовать для разного рода кэшей, а-ля memcached, или кэш самой OS
EP>4. свободную память можно использовать для space–time tradeoff — например отдавать хэштаблицам много места, чтобы реже получать коллизии.

5. Свободную память можно продать на радиорынке, а деньги пропить
Re[4]: асинхронная сериализация
От: Evgeny.Panasyuk Россия  
Дата: 29.12.13 18:48
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>>>Вторая задача решается довольно просто, если у вас есть некий итератор по этой древовидной структуре, который умеет по запросу выдавать следующий элемент. Тогда вы просто, по мере готовности сокета, обходите свою структуру с помощью этого итератора, и по кусочкам проталкиваете в сеть.

EP>>Так вопрос как раз в том, как этот итератор для древовидной структуры сделать. Учитывая то, что узлы структуры гетерогенные.
Pzz>Ну, если представить себе, что узлы структуры состоят из каких-то собственных данных и ссылок на подузлы, добавляем ссылку назад и храним в итераторе текущий узел, номер текущей ссылки на подузел и, если собственные данные достаточно большие, текущее положение в них.

В этом варианте много рантайм оверхеда — как минимум потому, что типы узлов разные (а это тянет за собой type erasure).
Если делать древовидную структуру, то тогда уже на Boost.Fusion, как я описал в первом сообщении.

EP>>Если серьёзно, то в общем случае при меньшем использовании памяти:

EP>>1. есть возможность полностью поместится в L3, что является огромным boost'ом для производительности.
Pzz>Скорее всего, вы на этом мало чего наиграете. Эта память, в которую вы один раз кладете, и один раз забираете. Причем забираете со скоростью сокета, т.е., весьма неторопясь. Пока за данными придут, из кэша они давно уже вылетят.

Когда вся используемая память помещается в L3 — в обычную RAM не надо ходить, а это дорогого стоит.
Re[5]: асинхронная сериализация
От: niXman Ниоткуда https://github.com/niXman
Дата: 29.12.13 20:28
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Когда вся используемая память помещается в L3 — в обычную RAM не надо ходить, а это дорогого стоит.

думается мне, ты слишком заигрался с оптимизацией

страшно представить, чтоб мне ставили такие ограничения на используемую память %)
соединений тоже десятки тысяч, но никаких ограничений на кол-во и размер буферов.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[10]: асинхронная сериализация
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.12.13 12:14
Оценка:
Здравствуйте, smeeld, Вы писали:

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


A>>почему *желательно*, обоснуйте.

S>Можно задать встречный вопрос?
S>Вы смотрели на ассемблерные листинги программ на C++ и C?
S>Если тот кошмар, который генерит компилятор с C++ по сравнению с тем, что получается с C подобного синтаксиса
S>способствует снижению латентности,
S> то этот мир не совершенен больше, чем предпологалось.

А можно на конкретных примерах? Просто чаще всего, С и С++ компиляторы имеют разные фронтенды и один и тот же backend, занимающийся оптимизацией.
Re[11]: асинхронная сериализация
От: Lazin Россия http://evgeny-lazin.blogspot.com
Дата: 30.12.13 12:18
Оценка:
Здравствуйте, niXman, Вы писали:

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


S>>Вы смотрели на ассемблерные листинги программ на C++ и C?

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

Так нельзя сказать в общем случае. Иногда С++ компилятор генерирует менее качественный код, а иногда — более качественный. Идентичный код они вообще будут компилировать одинаково. А еще все очень сильно зависит от приложения и опций компилятора.
Re[12]: асинхронная сериализация
От: Evgeny.Panasyuk Россия  
Дата: 30.12.13 12:37
Оценка:
Здравствуйте, Lazin, Вы писали:

L>Так нельзя сказать в общем случае. Иногда С++ компилятор генерирует менее качественный код, а иногда — более качественный. Идентичный код они вообще будут компилировать одинаково. А еще все очень сильно зависит от приложения и опций компилятора.


Общий случай не интересен. Действительно на C можно сделать код таким же быстрым как и C++. Дело в цене такого кода.
Элементарный пример:
template<typename I, typename P>
I find_if(I first, I last, P p)
{
    while(first != last)
    {
        if(p(*first))
            return first;
        ++first;
    }
    return first;
}
такой линейный поиск работает с:
  • любыми типами последовательностей
  • любыми типами элементов
  • любыми предикатами

    Попробуй получить такую же гибкость на C не потеряв производительность.
  • Re[3]: асинхронная сериализация
    От: Lazin Россия http://evgeny-lazin.blogspot.com
    Дата: 30.12.13 12:43
    Оценка:
    Здравствуйте, Evgeny.Panasyuk, Вы писали:

    EP>Мне интересна любая практика асинхронной сериализации. Если есть какой-то пример — с удовольствием послушаю, независимо от структуры (часть вопроса как раз в том, какие структуры для этого лучше подходят).

    Я думаю стоит искать и спрашивать не асинхронной сериализацией, ибо это какой-то франкенштейн, а инкрементальной. Думаю google в этом случае будет отдавать куда более релевантные результаты. Вот скажем некоторые ASN.1 компиляторы умеют генерировать код, способный инкрементально сериализовать и десериализовать данные.
    Асинхронность в этом случае прикручивается просто, например на тех же stackfull coroutines — насериализовали данных в буфер, отправили, насериализовали еще и тд, пока всю структуру не отправили.
    А асинхронная сериализация это какой-то булшит. У меня первая ассоциация — сериализация в отдельном потоке, асинхронно основному потоку выполнения.

    EP>Соединений десятки тысяч. Буфер для одного соединения может занимать до нескольких мегабайт. В среднем случае экономия порядка гигабайт.

    Ну на самом деле не факт. Тут все зависит от конкретных чисел. Нужно смотреть на пропускную способность разных подсистем, ведь одновременно, приложение не может обслуживать все эти десятки тысяч соединений, оно не может одновременно сериализовать много данных, скорее всего оно будет сериализовать numcpu*const структур данных в секунду, а потом асинхронно отправлять их. И далеко не факт, что если получится сделать инкрементальную сериализацию больших структур данных, пропускная способность приложения увеличится. Это, вероятно, позволит "кормить" одномоментно кормить данными больше соединений, но медленнее
    Re[13]: асинхронная сериализация
    От: Lazin Россия http://evgeny-lazin.blogspot.com
    Дата: 30.12.13 12:50
    Оценка: :))
    Здравствуйте, Evgeny.Panasyuk, Вы писали:

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


    L>>Так нельзя сказать в общем случае. Иногда С++ компилятор генерирует менее качественный код, а иногда — более качественный. Идентичный код они вообще будут компилировать одинаково. А еще все очень сильно зависит от приложения и опций компилятора.


    EP>Общий случай не интересен. Действительно на C можно сделать код таким же быстрым как и C++. Дело в цене такого кода.

    EP>Элементарный пример:
    EP>
    EP>template<typename I, typename P>
    EP>I find_if(I first, I last, P p)
    EP>{
    EP>    while(first != last)
    EP>    {
    EP>        if(p(*first))
    EP>            return first;
    EP>        ++first;
    EP>    }
    EP>    return first;
    EP>}
    EP>
    такой линейный поиск работает с:

    EP>
  • любыми типами последовательностей
    EP>
  • любыми типами элементов
    EP>
  • любыми предикатами

    EP>Попробуй получить такую же гибкость на C не потеряв производительность.


    Это уже вопрос культурных различий
    Вполне возможно, этот шаблон будет инстанциирован для двух-трех разных типов и его вполне возможно написать на Си несколько раз И вот этот код, вручную специализированый, будет работать быстрее, так как нет исключений, например, и не нужно сохранять данные для разворачивания стека в случае возникновения исключения. Для С++ программиста это звучит странно, но тем не менее, так написано большое количество хорошего кода.
  • Re[14]: асинхронная сериализация
    От: Evgeny.Panasyuk Россия  
    Дата: 30.12.13 13:06
    Оценка:
    Здравствуйте, Lazin, Вы писали:

    EP>>Попробуй получить такую же гибкость на C не потеряв производительность.

    L>Это уже вопрос культурных различий
    L>Вполне возможно, этот шаблон будет инстанциирован для двух-трех разных типов и его вполне возможно написать на Си несколько раз

    В том то и дело, что на C обычно пишут с использованием runtime полиморфизма — и не парятся, отсюда и все тормоза.
    Типичный пример — GLib:
    GTree *             g_tree_new_full                     (GCompareDataFunc key_compare_func,
                                                             gpointer key_compare_data,
                                                             GDestroyNotify key_destroy_func,
                                                             GDestroyNotify value_destroy_func);
    Или тот же qsort из стандартной библиотеки.

    L>И вот этот код, вручную специализированый, будет работать быстрее, так как нет исключений, например, и не нужно сохранять данные для разворачивания стека в случае возникновения исключения.


    1. Исключения использовать не обязательно.
    2. За счёт inline'инга компилятор может увидеть что там нет никаких исключений.
    3. На x64 используются zero-cost exceptions. Проверка кодов ошибок по всему callpath может быть даже медленней на happy-path чем исключения.

    L>Для С++ программиста это звучит странно, но тем не менее, так написано большое количество хорошего кода.


    В первую очередь "полезного" кода. Плохой код тоже может выполнять полезные функции.
    Re[4]: асинхронная сериализация
    От: Evgeny.Panasyuk Россия  
    Дата: 30.12.13 13:27
    Оценка:
    Здравствуйте, Lazin, Вы писали:

    L>Я думаю стоит искать и спрашивать не асинхронной сериализацией, ибо это какой-то франкенштейн, а инкрементальной. Думаю google в этом случае будет отдавать куда более релевантные результаты. Вот скажем некоторые ASN.1 компиляторы умеют генерировать код, способный инкрементально сериализовать и десериализовать данные.


    Хм. "инкрементально" — первая ассоциация это incremental backup, когда записывается цепочка diff'ов.
    Да и google выдает нечто похожее по incremental serialization — сериализацию последних изменений.

    L>Асинхронность в этом случае прикручивается просто, например на тех же stackfull coroutines — насериализовали данных в буфер, отправили, насериализовали еще и тд, пока всю структуру не отправили.


    Stackful coroutines везде прикручиваются легко.
    Например их без проблем можно использовать с Boost.Serialization, в котором нет никакой асинхронной/инкрементальной сериализации.

    L>А асинхронная сериализация это какой-то булшит. У меня первая ассоциация — сериализация в отдельном потоке, асинхронно основному потоку выполнения.


    Если бы я знал правильные keywords, которые привели бы меня туда, где есть практические примеры — я бы наверное тут и не спрашивал

    EP>>Соединений десятки тысяч. Буфер для одного соединения может занимать до нескольких мегабайт. В среднем случае экономия порядка гигабайт.

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

    Отчего же? На современных машинах bandwidth памяти ~30GiB/s — это upper bound для сериализации.
    Даже если сериализация будет жутко тормозной — сеть всё равно получится забить.
    Re[5]: асинхронная сериализация
    От: niXman Ниоткуда https://github.com/niXman
    Дата: 30.12.13 16:51
    Оценка:
    Здравствуйте, Evgeny.Panasyuk, Вы писали:

    о, вспомнил!
    у тебя же буфер фиксированного размера, так?
    насколько я помню, ты собирался переключать контекст после сериализации каждого мембера?
    а как быть, если какой-то мембер по объему не вмещается в буфер? переключать контекст еще и при заполнении буфера, прям посреди его сериализации?

    ты вот честно скажи, задача реальная или придуманная для разминки? и на каком девайсе твой код должен работать?
    пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.