Как стать автором
Обновить

Комментарии 24

Если не секрет, а чем именно вы сериализовали в Qt? Я не помню, чтобы там был соответствующий функционал, заглянул в документацию вроде только парсеры.
Я вообще сериализацию не сравнивал. Не интересно, ибо сериализатор пишется тривиально. Так что сравнение было только десериализаторов.
Простите, в мой комментарий можно читать сериализовали/десериализовали. Если я правильно понял вы использовали QJSON документ в своем приложении.
Просто если использовать QJSONDocument это несколько меняет подход, по скольку для десериализации в общем случае не обязательно строить полное дерево JSON документа как этой делает QJSONDocument(лишние накладные расходы). Я думал в Qt появился какой-то механизм который позволяет десериализовать JSON потоком.
Я его и использовал (QJsonDocument).
Потоком (если я правильно понял, что Вы имели в виду) десериализовать не получиться из-за текущей реализации парсера. Я глубоко не копал, но складывается впечатление, что для этого придется переписывать почти всю реализацию.
Да, все так и есть. Точнее будет как с XML 2 имплементации: stream reader и DOM. Надеюсь на скорейшее появление в Qt. Чуть не забыл, за статью спасибо! :)
М-да… Забыл указать местоположение самой библиотеки. Здесь она.
С DOM-style API получились следующие результаты:
Наилучшее время исполнения, с — 0.932,
Отношение к лидеру теста — 4.255708,
Среднее время исполнения, с — 0.95836,
Отношение к лидеру теста — 4.306849.

Я не думаю что SAX-style API что-то изменит, т.к. сообщение я парсю (паршу?) полностью.

В случае SAX-style API судя по example/messagereader/messagereader.cpp там все мрачно в плане юзабельности. В том смысле, что получаешь просто огрызки строк, следовательно, приводить их к значениям и проверять соответствие типам придется «в ручную».
В моем случае это делается автоматом.

Тем неменее у него есть преимущество — полная поддержка юникода. За свою библиотечку я пока не поручусь. Допилить возможно, но пока небыло необходимости.
А можно пример, как вы юзали DOM-style API? Там есть разные варианты, стоит с ними поиграть.
Использовал так
#include <jsmincpp/deserialize/Deserializer.h>

#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <stdint.h>
#include <iostream>

using namespace std;
using namespace rapidjson;

struct Data {
  double First;
  double Second;

  Data( )
      :
          First( 0.0 ),
          Second( 0.0 ) {
  }

  void Deserialize( Document &d ) {
    First = d [ "First" ].GetDouble( );
    Second = d [ "Second" ].GetDouble( );
  }
};

int main( ) {
  cout << "It's work!" << endl;

  double realResult = 0.0;
  double testResult = 0.0;

  char json [ ] =
      "{\"First\":X0.01,\"Second\":X0.01}";

  for ( uint32_t i = 0; i < 1000000; ++i ) {
    uint8_t t = i % 3;

    json [ 9 ] = '2' + t;
    json [ 24 ] = '3' + t;

    Document d;
    d.Parse( json );

    Data data;
    data.Deserialize( d );

    realResult += 20.01 + 30.01 + t * 20;
    testResult += data.First + data.Second;
  }
  cout
      << "RealResult = " << realResult << ", TestResult = " << testResult
      << endl;

  return 0;
}

Если есть идеи, готов проверить.
Из идей было попробовать doc.ParseInsitu (деструктивный парсер), но он даст профит только на строках, а в тесте только даблы.

Я бы в профайлере прогнал оба теста, чтобы точно знать что не так. Ну и сами тесты на более жирных объектах погонял (со строками, интами и прочим)
Хм. Посмотрим позже если руки дойдут. Тест так, больше как лакмусовая бумажка был.

Впрочем, если у кого-то будет желание провести более развернутые тесты был бы рад посмотреть результат. Я, всеж, лицо заинтересованное. Да и с даблами (первое, что под руку подвернулось, а потом переписывать бенчмарки не лень стало) мне могло повезти.
Ответил выше.
А какие средcтва контроля переполнения стека вы используете?
Если правильно понял, то чем ветвистее дерево JSON тем больше стека расходуется на его парсинг и в стек попадают каждый раз не только данные из ветвей но и весь контекст одной и той же рекурсивной функции. Или нет?
Никаких.

Пример.
  template < typename D, typename H >
  bool operator()( uint32_t hash, D &deserializer, H &handler ) {
    if ( Head::HASH == hash ) {
      bool ret = true;

       // Здесь создаем объект и заполняем его

      return ret;
    } else
      return Base_t::operator()( hash, deserializer, handler );
  }

Здесь четко видна рекурсия, но компилятор преобразует этот кусок к виду:

400997:	81 f9 53 c1 b0 53    	cmp    $0x53b0c153,%ecx
40099d:	0f 84 84 00 00 00    	je     400a27 <main+0x247>
4009a3:	81 f9 5f 14 b3 b1    	cmp    $0xb1b3145f,%ecx
4009a9:	74 15                	je     4009c0 <main+0x1e0>

А по поводу рекурсии и переполнения стека я перестал беспокоится после курса по скалке на Coursera'е. Я там тоже стек переполнял порой (и это в функциональном языке!). Как оказалось, не всякую рекурсию можно оптимизировать. Тем не менее каких-то страшилок нам не рассказывали, так слегка затронули вопрос оптимизации хвостовой рекурсии. Я это к тому, что народ, походу, на эту тему особенно не парится. Но помнить об этом, конечно, надо.

Весь получающийся код не исследовал. Но, вообще, стек должен расти не столько с ветвистостью дерева, сколько с увеличением глубины вложенности ветви.
Глубину вложенности в вашем смысле я и имел в виду.
А вы измеряли сколько стека расходуется в микроконтроллере на парсинг какого-нибудь тестового JSON файла?
На контроллере нет. Я уже уволился от-туда, где всем этим занимался. В принципе, собрать, дизассемблировать и проанализировать простенькое приложение можно. Что бы не терять время, скажите, Вас устроит разбор полетов на архитектуре x86_64 или принципиален контроллер (например, arm)?
Off-top: В каком-нибудь западном вузе за такую статью, добавив бла-бла в начале и бла-бла в конце, вполне можно схлопотать звание PhD. Серьёзно.
В каком? Где novelty? Да и где science вообще? Ph.D за Engineering не дают обычно. Я уж молчу, что о диссертации меньше чем на 50 страниц ни разу не слышал, и то это считается очень лаконично и воды там нет, скорее наоборот. Это ж сколько bla-bla?
Я вот тоже читаю «A Dissertation submitted for the Degree of Doctor of Philosophy» на тему связки RMIMDesigner и V3Generator и удивляюсь, а где же novelty, а как это вообще. И она не единственная подобная. Я этот процесс если не каждый день, то для каждой новой интеракции выполняю. Кому-то шишки, а кому-то PhD-ишки.
STL и использовать его на контроллере, в котором всего-то 1МБайт флеша и 198кБайт ОЗУ, мягко говоря, странно.
Вот уж не думал, что имея целый мегабайтище памяти жаба задавит использовать плюшки STL. Было б у вас 4 или 16k, тогда да.
М-м-м… А смысл? В том варианте весьма активно используются std::string и std::map, а значит, нужно управлять памятью. Нужен менеджер памяти, причем, многопоточный, т.к. использовалась операционка с вытесняющей многозадачностью. Я же обошелся только глобальной памятью и стеком. Причем в глобальной памяти у меня лежала только фабрика, очереди потоков и ивенты, дергаемые из прерываний.

Можно конечно использовать что-то вроде uSTL, например. Использовать STL, ради STL'я? Тем более, что я вполне обошелся своими силами.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации