NFX — Ультраэффективная Бинарная Сериализация в CLR

    Требования


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

    • самозацикленные графы объектов (деревья с back-references)
    • массивы структур (value types)
    • классы/структуры с readonly полями
    • инстансы существующих .Net коллекций (Dictionary, List), которые внутренне используют custom-сериализацию
    • большое кол-во инстансов типов, специализированных для конкретной задачи


    Речь пойдёт о трёх аспектах, которые очень важны в распределённых кластерных системах:

    • скорость сериализации/десериализации
    • объём объектов в сериализированном виде
    • возможность использовать существующие объекты без надобности “украшения” этих объектов и их полей вспомогательными атрибутами для сериализации


    Кратко рассмотрим три вышеперечисленных аспекта.

    Первое — скорость. Это очень важно для обеспечения общего быстродействия системы в распределённой среде, когда для выполнения задачи (например, запрос от одного пользователя) требуется исполнить пять-десять запросов на другие машины бэк-энда.

    Второе — объём. При перекачке/репликации большого кол-ва данных бюджет канала связи между датацентрами не должен “раздуваться”.

    Третье — удобство. Очень неудобно, когда только для сериализации/маршалинга требуется создание “лишних” объектов, ктр. переносят данные. Также неудобно заставлять программиста конкретного бизнес-типа писать низкоуровневый код по записи инстанса в массив байт. Может это и можно сделать, когда у вас 5-6 классов, но что делать, если в вашей системе 30 базовых generic классов (i.e. DeliveryStrategy), каждый из которых комбинируется с десятками других классов (это даёт сотни конкретных типов, i.e.: DeliveryStrategy, DeliveryStrategy, DeliveryStrategy etc.). Очень хотелось бы иметь прозрачную систему, которая может сериализировать практически все классы предметной области без надобности дополнительной разметки, кода и т.д. Конечно, есть вещи, которые не нужно сериализировать, например, какие-то unmanaged ресурсы или делегаты, но всё остальное обычно нужно, даже такие элементы как readonly поля структур и классов.

    Данная статья освещает тему именно бинарной сериализации. Мы не будем говорить о JSON и прочих форматах, так как они не предназначены для эффективного решения вышеупомянутых задач.

    Проблемы существующих сериализаторов


    Сразу оговоримся, всё, что тут написано, относительно — смотря что с чем сравнивать. Если вы пишите/читаете сотни объектов в секунду, то проблем нет. Другое дело, когда нужно обрабатывать десятки или даже сотни тысяч объектов в секунду.

    BinaryFormatter — ветеран .Net. Отличается простотой использования и подходит к требованиям лучше, чем DataContractSerializer. Хорошо поддерживает все встроенные типы коллекций и прочих BCL классов. Поддерживает версионность объектов. Не интероперабилен между платформами. Имеет очень большие недостатки связанные с производительностью. Он очень медленный и сериализация производит очень массивные потоки.

    DataContractSerializer — движок WCF. Работает быстрее BinaryFormatter’а во многих случаях. Поддерживает интероперабильность и версионность. Однако этот сериализатор не предназначен для решения general-purpose проблем сериализации как таковой. Он требует специализированной декорации классов и полей атрибутами, также имеются проблемы с полиморфизмом и поддержкой сложных типов. Это очень объяснимо. Дело в том, что DataContractSerializer не предназначен по определению для работы с произвольными типами (отсюда и название).

    Protobuf — суперскорость! Использует гугловский формат, позволяет менять версию объектов и супербыстрый. Интероперабилен между платформами. Имеет большой существенный недостаток — не “понимает” все типы автоматически и не поддерживает сложных графов.

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

    Исходя из вышеперечисленных характеристик, если не учитывать производительность, самый подходящий для нас сериализатор — это BinaryFormatter. Он наиболее “прозрачен”. То, что он не поддерживает интероперабельность между платформами, для нас не важно, т.к. у нас одна платформа — Unistack. Но вот скорость его работы просто ужасная. Очень медленно и большой объём на выходе.

    NFX.Serialization.Slim.SlimSerializer


    github.com/aumcode/nfx/blob/master/Source/NFX/Serialization/Slim/SlimSerializer.cs

    SlimSerializer является гибридным сериализатором с динамической генерацией ser/deser кода в рантайме для каждого конкретного типа.

    Мы не пытались сделать абсолютно универсальное решение, ибо тогда пришлось бы жертвовать чем-то. Мы не делали вещи, которые. для нас неважны, а именно:
    • кросс-платформенность
    • object version upgrade


    Исходя из вышесказанного, SlimSerializer не подходит для таких задач, где:
    • данные хранятся в storage (например, на диске)
    • данные генерируются/принимаются процессами не на CLR-платформе, однако Windows.NET — to — Linux.MONO и Linux.MONO — to — Windows.NET работают великолепно


    SlimSerializer предназначен для ситуаций, когда:
    • нужна большая скорость (сотни тысяч операций в секунду)
    • требуется экономить объём передаваемых данных
    • специализированная разметка для сериализации нереальна по разным причинам (например, очень много классов)


    SlimSerializer поддерживает всевозможные edge-case’ы, например:
    • прямая сериализация примитивных структур и их Nullable эквивалентов (DateTime, Timespan, Amount, GDID, FID, GUID, MethodSpec, TypeSpec etc.)
    • прямая сериализация основных reference-типов (byte[], char[], string[])
    • поддержка классов и структур с read-only полями
    • поддержка custom-сериализации ISerializable, OnSerializing, OnSerialized… etc.
    • каскадно-вложенная сериализация (например, какой-то тип делает custom-сериализацию себя и должен вызвать SlimSerializer для какого-то поля)
    • позволяет сериализировать любые поддерживаемые типы (кроме делегатов) в корень
    • нормализует графы любой сложности и вложенности
    • детекция buffer-overflow в десериализации (это нужно, когда стрим корраптается и возможно непреднамеренное выделение большого куска памяти)


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

    Как это работает?

    SlimSeralizer использует стриммер, который берётся из injectable формата github.com/aumcode/nfx/blob/master/Source/NFX/IO/StreamerFormats.cs. Стриммер-форматы нужны для того, чтобы сериализировать определённые типы напрямую в поток. Например, мы по умолчанию поддерживаем такие типы как FID, GUID, GDID, MetaHandle etc. Дело в том, что определённые типы можно хитро паковать variable-bit энкодингом. Это даёт очень большой прирост в скорости и экономит место. Все integer-примитивы пишутся variable-bit энкодингом. Таким образом, в случаях, когда нужна супербыстрая поддержка специального типа, можно унаследовать StreamerFormat и добавить WriteX/ReadX методы. Система сама собирает и превращает их в лямбда-функторы, которые нужны для быстрой сериализации/десериализации.

    Для каждого типа строится TypeDescriptor github.com/aumcode/nfx/blob/master/Source/NFX/Serialization/Slim/TypeSchema.cs., который динамически компилирует пару функторов для сериализации и десериализации.

    SlimSerializer построен на идее TypeRegistry и это главная изюминка всего сериализатора github.com/aumcode/nfx/blob/master/Source/NFX/Serialization/Slim/TypeRegistry.cs. Типы пишутся как строка — полное имя типа, но если такой тип уже встречался ранее, то пишется type handle вида “$123”. Это обозначает типа, находящийся в регистратуре за номером 123.

    Когда мы встречаем reference, то заменяем его на MetaHandle github.com/aumcode/nfx/blob/master/Source/NFX/IO/MetaHandle.cs, который эффективно инлайнает либо строку, если reference на string, либо integer, который является номером инстанса объекта в графе объектов, т.е. своеобразный псевдо-поинтер-хэндл. При десериализации всё реконструируется в обратном порядке.

    Производительность


    Все нижеприведённые тесты производились на Intel Core I7 3.2 GHz на одном потоке.
    Производительность SlimSerializer масштабируется пропорционально кол-ву потоков. Мы применяем специализированные thread-static оптимизации, дабы не копировать буфера.

    Возьмём следующий тип в качестве “подопытного”. Обратите внимание на всевозможные атрибуты, которые нужны для DataContractSerializer:

    [DataContract(IsReference=true)]
    [Serializable]
    public class Perzon
    {
          [DataMember]public string FirstName;
          [DataMember]public string MiddleName;
          [DataMember]public string LastName;
    
          [DataMember]public Perzon Parent;
     
          [DataMember]public int Age1;
          [DataMember]public int Age2;
          [DataMember]public int? Age3;
          [DataMember]public int? Age4;
     
          [DataMember]public double Salary1;
          [DataMember]public double? Salary2;
    
          [DataMember]public Guid ID1;
          [DataMember]public Guid? ID2;
          [DataMember]public Guid? ID3;
      
          [DataMember]public List<string> Names1; 
          [DataMember]public List<string> Names2;        
          
          [DataMember]public int O1 = 1;
          [DataMember]public bool O2 = true;
          [DataMember]public DateTime O3 = App.LocalizedTime;
          [DataMember]public TimeSpan O4 = TimeSpan.FromHours(12);
          [DataMember]public decimal O5 = 123.23M;
    }
    


    А теперь делаем много раз по 500 000 объектов:
    • Slim serialize: 464 252 ops/sec; size: 94 bytes
    • Slim deser: 331 564 ops/sec
    • BinFormatter serialize: 34 702 ops/sec: size: 1188 bytes
    • BinFormatter deser: 42 702 ops/sec
    • DataContract serialize: 108 932 ops/sec: size: 773 bytes
    • DataContract deser: 41 985 ops/sec


    Скорость сериализации Slim к BinFormatter: в 13.37 раз быстрее.
    Скорость десериализации Slim к BinFormatter: в 7.76 раз быстрее.
    Объём Slim к BinFormatter: в 12.63 раз меньше.

    Скорость сериализации Slim к DataContract: в 4.26 раз быстрее.
    Скорость десериализации Slim к DataContract: в 7.89 раз быстрее.
    Объём Slim к DataContract: в 8.22 раз меньше.

    А теперь пробуем сложный object-граф из нескольких десятков взаимно ссылающихся объектов, включая массивы и листы (много раз по 50 000 объектов):
    • Slim serialize: 12 036 ops/sec; size: 4 466 bytes
    • Slim deser: 11 322 ops/sec
    • BinFormatter serialize: 2 055 ops/sec: size: 7 393 bytes
    • BinFormatter deser: 2 277 ops/sec
    • DataContract serialize: 3 943 ops/sec: size: 20 246 bytes
    • DataContract deser: 1 510 ops/sec


    Скорость сериализации Slim к BinFormatter: в 5.85 раз быстрее.
    Скорость десериализации Slim к BinFormatter: в 4.97 раз быстрее.
    Объём Slim к BinFormatter: в 1.65 раз меньше.

    Скорость сериализации Slim к DataContract: в 3.05 раз быстрее.
    Скорость десериализации Slim к DataContract: в 7.49 раз быстрее.
    Объём Slim к DataContract: в 4.53 раз меньше.

    Обратите внимание на разницу при сериализации типизированного класса (первый случай “Perzon”) и второй (много объектов). Во втором случае есть сложный граф с циклическими взаимосвязями объектов и поэтому Slim начинает приближаться (замедляться) по скорости к Microsoft’у. Однако всё равно превосходит последний минимум в 4 раза по скорости и в полтора раза по объёму. Код на этот тест: github.com/aumcode/nfx/blob/master/Source/Testing/Manual/WinFormsTest/SerializerForm2.cs#L51-104

    А вот здесь сравнение с Apache.Thrift: blog.aumcode.com/2015/03/apache-thrift-vs-nfxglue-benchmark.html.
    Хоть эти цифры и не по чистой сериализации, а по всему NFX.Glue (который включает в себя мэссаджинг, TCP networking, security etc), скорость очень сильно зависит от SlimSerializer, на котором построены “родные” байндинги NFX.Glue.

    Each test is:
       64,000 calls each returning a set of 10 rows each having 10 fields
      640,000 total rows pumped
     
    Glue:     took  1982 msec @ 32290 calls/sec
    Thrift1:  took 65299 msec @   980 calls/sec  32x slower than Glue
    Thrift2:  took 44925 msec @  1424 calls/sec  22x slower than Glue
    =================================================================
    Glue is:
       32 times faster than Thrift BinaryProtocol
       22 times faster than Thrift CompactProtocol
    


    Итоги


    NFX SlimSerializer даёт исключительно высокий и предсказуемо устойчивый перформанс, экономя ресурсы процессора и памяти. Именно это открывает возможности для технологий высокой нагруженности на CLR платформе, позволяя обрабатывать сотни тысяч запросов в секунду на каждом узле distributed систем.

    У SlimSerializer’а есть несколько ограничений, обусловленных невозможностью создать практическую систему “one size fits all”. Эти ограничения: отсутствие версионности структур данных, сериализации делегатов, интероперабильности с другими платформами кроме CLR. Однако стоит заметить, что в концепции Unistack (унифицированный стэк software для всех узлов системы) эти ограничения вообще незаметны кроме отсутствия версионности, т.е. SlimSerializer не предназначен для длительного хранения данных на диске, если структура данных может поменяться.

    Ультра-эффективные native байндинги NFX.Glue позволяют обслуживать 100 тысяч + двусторонних вызовов (two-way calls) в секунду благодаря специализированным оптимизациям, применяемым в сериализаторе, при этом не требуя от программиста лишней работы по созданию extra data-transfer типов

    youtu.be/m5zckEbXAaA

    youtu.be.com/KyhYwaxg2xc


    SlimSerializer значительно обгоняет встроенные в .NET средства, позволяя эффективно обрабатывать сложные графы взаимосвязанных объектов (чего ни Protobuf, ни Thrift делать не умеют).
    Метки:
    Поделиться публикацией
    Комментарии 40
    • +5
      А сами тесты производительности есть в Гите? и почему в самих результатах нет Protobuf?
      • –1
        да конечно, там жэ указаны соурсы тестов
        смотрите тут:

        github.com/aumcode/nfx/blob/master/Source/Testing/Manual/WinFormsTest/SerializerForm2.cs

        это именно "ручные кликабельные" тесты для винды и линукса

        несколко сотен интеграйшон тестов там нет т.к. они в другой закрытой базе.

        унит тест на Слим:
        github.com/aumcode/nfx/tree/master/Source/Testing/NUnit/NFX.NUnit/Serialization

        протобуф эти тести в принципе не проидет — там цикли объектов
        • 0
          Ок, но меня интересует применимость для моего случая — у меня много линейных больших DTO, которые я сериализую протобафом. Вот и вопрос — имеет ли смысл пробовать ваш сериализатор для моего случая.
          • 0
            сделайте тест. думаю что скорость Слим будет такой-же как протобуф для линейнои структуры или может Слим будет процентов на 10 медленнее т.к. мы же делаем намного больше (например разруливаем ссылки),
            ОДНАКО ЕСЛИ вы правилно поставите TypeRegistry и батчинг моде в Слим можно будет обрабатывать быстрее — мне надо знать во что (в поток, в фаил, сокет, етц..)
            идут ваши данные и как вы их читаете назад (по 1 по батчу етц.)
        • 0
          А как насчет MsgPack? Или Avro?
          • 0
            это сериализатори «general purpose» — они не могут сериализуроват сушествуюшие CLR типы прозрачно.
            попробуите перенести Dictionary<string, Dictionary<FID, Node>> на другую машину.

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

            Авро мы смотрели пару лет назад, и остались разочарованы качеством и багами. Извините, детали тестов не сохранились — врать не буду
            • +1
              сложные цикличесние графы вообще в JSON-подобные форматы автоматически не пишутся.
              JSON.NET умеет без особых проблем, надо только включить в конфиге.
              • 0
                знаем, но это медленно.

                Ранше они не умели делать классы которые сами себя пишут через [OnSer/Deser***]/ISerializable.
                Даже если это заработало — все равно медленно будет ибо ни JSON ни BSON не могут делать кастом битмаппинг для специалных типов.

                Кстати классный баг — Dicitonary<string, object>(CultureInvariantStringComparer) компарер рушил CLR — с unmanaged exception from mscrolib из-за нрепрабилного вызова [OnDeserialized...]
            • 0
              Взгляд со стороны: под JVM уже много лет различные библиотеко-писатели упражняются в написании самых быстрых, самых компактных и самых удобных сериализаций, посмотрите хотя бы это: github.com/eishay/jvm-serializers/wiki, хотя и там много разработок не упомянуто.

              Вопрос: CLR — непаханое поле в этом плане?
              • +1
                В.НЕТ очен много тоже всего есть.

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

                Слим сериализатор может побить многие сериализаторы только по 1й причине.
                У нас UNISTACK- т.е. все наше, а значит мы можем делать «special treatment» для всяких системных структурок
                которие исползуются ДРУГИМИ узлами нашей болшой сыстемы.
                Например, знает ли MsgPack ili Avro ili Thrift ili ProtoBuf про какие-то специалные крючки для репликации данных в ДБ — конечно нет, и не должен,
                но тогда заплатите за скорость.
                • 0
                  Вот здесь есть сравнение производительности наиболее известных сериализаторов в .NET: theburningmonk.com/2015/04/binary-and-json-benchmarks-updated-2
                  Кстати, если верить результатам, то некоторые JSON сериализаторы уже почти догнали protobuf, а в некоторых ситуациях могут и обгонять (по-крайней мере по тестам самих авторов).
                • +3
                  Кстати, Степанов вещает много похожего на UNISTACK, например: youtu.be/QmuMHtbO4ug и youtu.be/Dx1MZh6KYCk Но скорее как о далекой мечте, и когда-то в СССР был банк алгоритмов, и на западе в 60х-70х много говорили о сертифицированных, много раз проверенных алгоритмах (по которым собирается статистика и глобальная степень перееиспользования для которых должна быть такой огромной, что в них уже не может быть ошибок). Вообще идея того, что должен быть один язык, одна библиотека, один подход, одна архитектура, один фюрер летает в воздухе с самого основания программирования, как дисциплины. Только в последние 10 лет началась эта отрава в умах, что «нельзя решить все задачи одним языком» или «для каждого случая хорош свой инструмент». Разве не очевидно, что эти принципы не противоречат друг-другу, только тогда есть свои инструменты для каждого случая, когда в основе всего этого разнообразия инструментов лежит один фундамент. Языки и инструменты должны быть построены в нечто вроде дерева, где на каждом более высоком слое происходит разветвление (специализация), а на каждом более низком — обобщение (унификация). В конечном счете, в основе всего лежит математика, как самый абстрактный способ моделирования и физика, как база для создания моделирующих машин. А сейчас в программировании такая ситуация, что все разнообразие порождено не необходимостью специализации, а волюнтаризмом или жадностью. Волюнтаризмом т.е. произволом разработчиков, мол захотелось — я и сделал. И жадностью гигантов ИТ индустрии — которым нужны свои, непохожие ни на что, инструменты и языки только для порождения искусственной несовместимости. Неспецифическая конкуренция, когда специфики нет, а различие придумано искусственно — загадило нам все программирование. Но как, как двигаться к юнистеку? Как двигаться к одним стандартам? Как двигаться к обобщению, если все плывут в другую сторону? У меня только один ответ — отходить в сторону и делать все самому, да, это первое время порождает +1 к хаосу и фрагментации инструментов и языков, но стоит кому-то начать, и сделать что-то безапелляционно хорошо, как вот с Линуксом, с nginx, с V8 и c другим открытым ПО получилось, то за ним потянутся.
                  • –2
                    100% согласен.
                    вы прямо «расскусили» то что мы делаем уже несколько лет с НФХ.
                    вообще очень хорошо, что до МС дошло наконец, что сидеть со своим CLR-закрытым кодом
                    как казначей на сундуке в замке кощея — себе дороже. они осознали что кащей смертен — и открыли
                    ядро. эти потуги шли в Микрософте уже пару лет.

                    одно можно сказать, или даже ДОКАЗАТЬ — чем меньше кода и он проще — тем лучше.
                    современный software stack поломан. Как может быть простой MVC для веба у Микрософта — сотни тысяч или даже миллионы
                    строчек?

                    Смотрим сюда, это весь MVC, где код? И он делает всё что нужно (routing, action filtering, security, param binding, complex data JSON/multipart etc..). Где код? Его нет! < 1500 loc

                    github.com/aumcode/nfx/tree/master/Source/NFX.Wave/MVC

                    это я как раз про модели математические мира. Они есть (как формы Платона) хотим мы того или нет — сама суть
                    структуры мира. Вопрос только в интерпритации — а индикатор правилного пути — простота и легкость

                    аум!
                    • +1
                      github.com/aumcode/nfx/tree/master/Source/NFX.Wave/MVC
                      Не вижу работу с асинхронностью. Не вижу кеширования метаданных. Перфоманс скорее всего там не живет.

                      Работы с middleware типа OWIN не замечено. Свои биндинги параметров не написать. Возможности настроить и использовать свой Service Locator/Container нет. Зато полно каких то костылей. Кому нужен такой недоделаный велосипед (вопрос риторический)?

                      Это беглый осмотр. Если провести сравнение по полному фичелисту, то будет еще более грусно.
                      • +1
                        по пунктам которые вы затронули:
                        асинхронность:
                        github.com/aumcode/nfx/blob/master/Source/NFX.Wave/WorkContext.cs#L233
                        +hybrid injectable dispatcher

                        кэш метаданных:
                        github.com/aumcode/nfx/blob/master/Source/NFX.Wave/Handlers/TypeLookupUtils.cs
                        github.com/aumcode/nfx/blob/master/Source/NFX.Wave/MVC/Reflection.cs

                        скорость: запросто 100 000 запросов в секунду отвечая JSON на запрос с параметрами, и это все с паттерн матчингом и штук 6 фильтров. МС МВЦ даже близко так не может
                        берите здесь и убедитесь сами:
                        github.com/aumcode/nfx/blob/master/Source/Testing/Manual/WaveTestSite/Controllers/Tester.cs#L75-90

                        OWIN? а зачем он нам? У нас все своё (UNISTACK методология), такжэ мы не поддерживаем ЯваБеанс и еще около 50К стандартов :)

                        параметры:
                        github.com/aumcode/nfx/blob/master/Source/NFX.Wave/Handlers/MVCHandler.cs#L171-L230
                        github.com/aumcode/nfx/blob/master/Source/NFX.Wave/MVC/Attributes.cs#L172-182

                        Локатор/Контаинер? А это что?
                        github.com/aumcode/nfx/blob/master/Source/Testing/Manual/WaveTestSite/Program.cs
                        github.com/aumcode/nfx/blob/master/Source/Testing/Manual/WaveTestSite/WaveTestSite.laconf#L136-423

                        локатор:
                        github.com/aumcode/nfx/blob/master/Source/Testing/Manual/WaveTestSite/WaveTestSite.laconf#L254

                        этот «велосипед» имеет намного болше возможностеи чем Ms MVC, проше и быстрее на порядок.
                        На этом написано реално несколко сайтов которые держат устойчиво десятки тысяч запросов/секунду
                        • 0
                          асинхронность: github.com/aumcode/nfx/blob/master/Source/NFX.Wave/WorkContext.cs#L233
                          Сожалею, но на семафорах и тредах это не асинхронность, это синхронизация.
                          кэш метаданных:
                          Проглядел. В коде очень сложно проследить за зависимостями.

                          >скорость: запросто 100 000
                          Пока ваш фреймворк не появится хотя бы тут, ваши заявления не имеют значения. Вы можете тестировать на железе которое может выдать и 200к запросов на другом фреймворке.
                          параметры:
                          Не очень удобно. Но да, биндинги.

                          Локатор/Контаинер? >А это что?
                          Я хочу свой же. Там написано. Я хочу к примеру Ninject или Autofac, и логи от log4net.

                          >На этом написано реално несколко сайтов
                          А на ASP.NET MVC не «несколько сайтов» :)

                          • 0
                            нигде и не появится, нам не нужен ПР.
                            у нас цель зацепить талантливых русских ребят себе в комманду — что мы и сделали меньше чем за 5 дней от публикации кода в гит хуб.

                            интересно обозревать динамику Хабра — болшинство комментариев вообще не в тему, флайм и высер.

                            то что вы «хотите» авто-фак или нинджект — вы бы сначала почитали статью
                            и материалы про UNISTACK:
                            github.com/aumcode/nfx/wiki/NFX-Unistack-Overview

                            ну а аффто-фак нам не очен хочется применять

                            удачи
                            • 0
                              про асинхронность — я с вами 100% согласен, но вы невмнимательно посмотрели в код.
                              WAVE — это гибридный сервер, в нем не такая модель обработки как в ИИС или АСП.НЕТ
                              хотя может быть и такой. То что я вам показал — ето режим работы когда HTTP Work,

                              github.com/aumcode/nfx/blob/master/Source/NFX.Wave/WorkContext.cs#L233

                              , никто болше не владеет. Здесь можно делат намного более гибкие модели процессинга,
                              например 1 сред на 10,000 клиентов доставляет им чат. У нас нет всех этих «костылеи»
                              для реактивного программирования. Все делается намного проше за счет того что все
                              исползует уже написанниы код и МОЖЕТ положится на него всегда, например на App.Log или
                              на Апп.Glue. Т.е. — ви можете пропросить не убивать WorkContext- и манаджать его сами именно тем
                              паттерном который нужен для решения задачи, что намного гибче чем ASYNC AWAIT на уровне конкретных актионс
                              • 0
                                Чем больше я вас читаю, тем больше у меня создается ощущение, что вы все сделали/знаете, как сделать, лучше, чем MS. Я правильно вас понял?
                                • 0
                                  а, что для вас микрософт и статуя свободы есть абсолутный эталон?
                                  а как же может тогда быть такое что например Node, Rubi и Puthon, Erlang etc… живут и процветают?

                                  каждый тоол хорош для того для кого он хорош.

                                  задача михрософта — разводить сотни тысяч девелоперов на «самое новое» — перекладывая из пустого в порожнее,
                                  и держать цену акций, которые все ребята умные давно продали (вклучая самого Била)

                                  мы ничего не продаём в области ИТ технологий.
                                  я написал — наша задача была знакомство с талантливыми ребятами именно из СССР.

                                  если вам интересно, есть по -делу вопросы, пишите!
                                  • +1
                                    Нет, для меня Microsoft — это производитель определенного количества технологий и фреймворков. В том числе, и тех, которыми пользуетесь вы. Но в предлагаемом вами решении вы последовательно отвергаете многое (если не все) из того, что они предлагают — сериализацию, TPL, более высокоуровневые решения (я уже не говорю про архитектурные решения, навроде того же DI).

                                    Вот мне и интересно: вы это делаете потому, что считаете, что все эти вещи реализовали лучше?
                                    • +1
                                      Есть вещи — как музыка Баха — вне времени — классика.

                                      CLR — написан очень хорошо, и меня никогда не подводил — работает предсказуемо и позволяет решать 99.8% задач.
                                      C# — очен хорошо продуманная, и универсальная вешь
                                      90% построенного вокруг етого — просто ужасно — и это потому что МС не можeт все зачеркнуть легаси.

                                      Например вообше XML/SOAP — это мода 90х годов. Сеичас REST, а суть тажа. А через 10 лет будет RPC- и все будут кричать что толко RPC!, then again ZML-2, XAML, FARMl, YAML etc…

                                      А *nix концепции не менялис 30 лет. До сиц пор ест grep, awk, bash, C, C++,…

                                      Будет ли Microsoft ASP.NET через 5 лет? — (популярен) — уже начался исход, и АСП 5 — не имеет ничего обшего с тем что было раньше, — just the name «ASP»

                                      вот есть все-таки классный софт: Линух Кернел, ОРАКЛ, Делфи (до версии 7 в свое время), МонгоДБ, его не так много…
                                      а есть тонны мусора — это 10000 билиотек которие делают все тоже самое 150 тысяч раз. — например логгинг в текстовый фаил
                                      в итоге очен сложно все ето охватит и поддерживать.

                                      наша библиотека тоже мусор для вас, и для 99%.НЕТ community Но для 0.01% ето именно то что надо.
                                      • +1
                                        Спасибо, что вы так и не ответили на мой вопрос.
                                        • 0
                                          вы можте задат конкретно вопрос?

                                          с радостью отвечу очен детално вклучая код и референсы.

                                          почемы мы обходим 90%.НЕТ стака?

                                          отвечаю: потому что нам удалось создать совсем другого уровня систему для распределенного обслужйвания
                                          клиентов, где объемы данних и транзакций были таковыми, что МС технологии вообше не предназначены для этого.
                                          была разработана методология UNISTACK — в ней мы работаем болше 20 лет и толко сеичас мы решили поделится своим опытом дабы привлеч мозги — поэтому пыбликация на Хабре
                                          • 0
                                            Ну то есть, я правильно вас понимаю: вы обходите 90% .net, потому что ваша реализация той же функциональности (в нужном вам объеме, конечно) — лучше?
                                            • 0
                                              А зачем что-то домысливать в нечетких терминах лучше/хуже, если можно просто сделать эксперимент и измерить.
                                              • +1
                                                Я не очень понимаю, как померять вещи вроде «намного более гибкие модели процессинга» (vs TPL), выигрыш/потери от отказа от async/await, преимущества от фиксированного DI и так далее.
                                                • +1
                                                  Можно померить комплексную производительность систем, решающих одинаковые задачи, созданные на базе разных технологий. И еще очень важно померить производительность программистов, использующих эти тулы. Если можно задачу решить быстрее, то преимущество очевидно, если поддерживать систему дешевле, то этот качественный показатель уже можно подсчитать количественно. Могут быть конечно такие случаи, когда преобразование качественных показателей в количественные само по себе очень ресурсоемко и мы не можем сделать такой эксперимент. В этом случае можно использовать метод экспертных оценок. И уже в самом страшном случае мы можем признать, что вопрос выходит за пределы человеческого познания, но до таких вопросов еще добраться нужно.
                                                  • +2
                                                    Можно. Все можно. Но чтобы это «померять» имело какое-то адекватное значение, должны быть выполнены n условий (например, должна быть одинаковая квалификация программистов). Добротное такое исследование в долгосрочной перспективе.

                                                    Но мне-то интересно другое. Когда человек, читающий мой код, задает мне вопрос «почему ты здесь используешь не стандартное X, а твое Y», у меня обычно есть ответ — «мое Y лучше» или «X не умеет вот так» или «когда писали, X не было» или «я про X не знал» или еще сколько-то разных. И мне интересен как раз такой субъективный ответ автора.
                                                    • +1
                                                      Одинаковая квалификация программистов не обязательна, это условие сложно реализовать, проще провести серию измерений и иметь репрезентативную выборку, чтобы разница в квалификации была сглажена. Конечно есть интуиция специалиста, основанная на опыте, и очевидно, что если человек что-то делает, то он верит в то, что делает, а то бы не делал и не писал бы нам эту статью. Я Вам скажу, что за свои 20 лет профессионального опыта программирования я неоднократно наблюдал, как один человек мог сделать лучше, чем сотни профессионалов и серьезные ИТ гиганты. Лишь потому, что этим гигантам вовсе не нужно делать хорошо, им нужно зарабатывать деньги и обеспечивать регулярность продаж, захватывать первенство на рынке, завоевывать лояльность потребителя любыми способами, вплоть до очевидного зомбирования. Для решения этих задач любой продукт должен иметь целый ряд заранее продуманных изъянов и в концепциях и в реализациях. Отсюда нарочная несовместимость, чрезмерная сложность, закрытость кода, чтобы даже научиться это делать было невозможно без вложения больших денег и сертификации.
                      • +1
                        В виде пакета не думали сделать?
                      • 0
                        Проблема в том, что protobuf и thrift кроссплатформенные. Этими пакетами можно обмениваться с любыми другими платформами на любых поддерживаемых языках.
                        А с вашим увы и ах.
                        • +2
                          это не проблема а СПЕЦИАЛНО так сделано. Почитайте пост внимательно — там это описано подробно
                        • 0
                          Удивлен тестом Thrift, не указано ничего из конфигурации трифта, о том какой стек тестировался и т.п., а без этого судить о скорости в рамках мы в 20 раз быстрее как минимум не серьезно.

                          Почему нет исходников тестов трифта?

                          Сериализация в thrift реализована очень близко к «очень быстрому» proto, с оговоркой на возможность использования различных форматов данных.
                          • 0
                            И да качеством кода трифта для C# я был разочарован :)
                            • 0
                              blog.aumcode.com/2015/03/apache-thrift-vs-nfxglue-benchmark.html

                              соурса на тест Трифт в НФХ нет, — не могу забивать свой код

                              если вам очень надо — я могу попросить своего партнёра отыскать исходник этого теста.
                              пишите в скайп: i...t..ad..a.p.t.er(точки удалить)
                            • +2
                              Хорошая работа, но ту ли проблему решаем. Protobuf, Thrift и тот же WCF дают явное определение интерфейсов, програмист должен задуматься что должно выдавтся за границы системы/сервиса, а что нет.
                              А автоматические генераторы, сериализаторы размывают физические границы системы что для ленивого програмиста/архитектора создаёт соблазн сделать сильно связаную систему где на каждый чих мы переганяэм мегабайты через сеть.
                            • 0
                              BTW где сравнение с главным хранилищем (качественных и оттестированных) велосипедов ServiceStack?

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