Комментарии 24
Если не секрет, а чем именно вы сериализовали в Qt? Я не помню, чтобы там был соответствующий функционал, заглянул в документацию вроде только парсеры.
Я вообще сериализацию не сравнивал. Не интересно, ибо сериализатор пишется тривиально. Так что сравнение было только десериализаторов.
Простите, в мой комментарий можно читать сериализовали/десериализовали. Если я правильно понял вы использовали QJSON документ в своем приложении.
Просто если использовать QJSONDocument это несколько меняет подход, по скольку для десериализации в общем случае не обязательно строить полное дерево JSON документа как этой делает QJSONDocument(лишние накладные расходы). Я думал в Qt появился какой-то механизм который позволяет десериализовать JSON потоком.
Просто если использовать QJSONDocument это несколько меняет подход, по скольку для десериализации в общем случае не обязательно строить полное дерево JSON документа как этой делает QJSONDocument(лишние накладные расходы). Я думал в Qt появился какой-то механизм который позволяет десериализовать JSON потоком.
Я его и использовал (QJsonDocument).
Потоком (если я правильно понял, что Вы имели в виду) десериализовать не получиться из-за текущей реализации парсера. Я глубоко не копал, но складывается впечатление, что для этого придется переписывать почти всю реализацию.
Потоком (если я правильно понял, что Вы имели в виду) десериализовать не получиться из-за текущей реализации парсера. Я глубоко не копал, но складывается впечатление, что для этого придется переписывать почти всю реализацию.
С DOM-style API получились следующие результаты:
Наилучшее время исполнения, с — 0.932,
Отношение к лидеру теста — 4.255708,
Среднее время исполнения, с — 0.95836,
Отношение к лидеру теста — 4.306849.
Я не думаю что SAX-style API что-то изменит, т.к. сообщение я парсю (паршу?) полностью.
В случае SAX-style API судя по example/messagereader/messagereader.cpp там все мрачно в плане юзабельности. В том смысле, что получаешь просто огрызки строк, следовательно, приводить их к значениям и проверять соответствие типам придется «в ручную».
В моем случае это делается автоматом.
Тем неменее у него есть преимущество — полная поддержка юникода. За свою библиотечку я пока не поручусь. Допилить возможно, но пока небыло необходимости.
Наилучшее время исполнения, с — 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 тем больше стека расходуется на его парсинг и в стек попадают каждый раз не только данные из ветвей но и весь контекст одной и той же рекурсивной функции. Или нет?
Если правильно понял, то чем ветвистее дерево JSON тем больше стека расходуется на его парсинг и в стек попадают каждый раз не только данные из ветвей но и весь контекст одной и той же рекурсивной функции. Или нет?
Никаких.
Пример.
Здесь четко видна рекурсия, но компилятор преобразует этот кусок к виду:
А по поводу рекурсии и переполнения стека я перестал беспокоится после курса по скалке на Coursera'е. Я там тоже стек переполнял порой (и это в функциональном языке!). Как оказалось, не всякую рекурсию можно оптимизировать. Тем не менее каких-то страшилок нам не рассказывали, так слегка затронули вопрос оптимизации хвостовой рекурсии. Я это к тому, что народ, походу, на эту тему особенно не парится. Но помнить об этом, конечно, надо.
Весь получающийся код не исследовал. Но, вообще, стек должен расти не столько с ветвистостью дерева, сколько с увеличением глубины вложенности ветви.
Пример.
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 файла?
А вы измеряли сколько стека расходуется в микроконтроллере на парсинг какого-нибудь тестового JSON файла?
Не знаю как по быстродействию, но по удобству всех уделывает github.com/nlohmann/json
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'я? Тем более, что я вполне обошелся своими силами.
Можно конечно использовать что-то вроде uSTL, например. Использовать STL, ради STL'я? Тем более, что я вполне обошелся своими силами.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Масштабируемая библиотека сериализации/десериализации JSON