Comments.blogs

А как вы работаете с xml?

19 мар 2007 10:18
0
(Текст записи скрыт. Показать...)
Интересно, как сейчас в разных компаниях обстоит дело с работой с xml форматом? Используете или нет? Если да, то какие средства для чтения\записи? Какие именно фичи из xml используется?
Есть мнение, что мы изобретали в очередной раз свой велосипед – хотелось бы это обсудить и понять, так ли это .
Вкратце про эволюцию работы с xml у нас в Лесте читай в блоге...


Началась наша работа с xml с парсера TinyXml. Достаточно удобный и простой парсер. Его просто подключить, просто использовать. Его минусы проявляются только когда появляются огромные xml файлы или когда надо работать с частями этих файлов, хранить subNodes и т.п. – тут начинаются тормоза и проблемы с памятью. Также проблемой являлось то, что не было типизации – в любую ноду можно было записать все, что угодно и только в момент загрузки можно было сконвертировать в нужный тип из строки.
Вот кусок такого файла:

<IconName value="DE_PC1000"/>
<Icon value="TL/Icon/Ammo/DE_PC1000"/>
<ExploPower value="150"/>
<IsBomb value="true"/>

Дальнейшим шагом было написание товарищем Corvax (http://www.dtf.ru/person/info.php?id=1212) системы классов, имеющих у нас кодовое имя SMCC. Это фактически был набор классов, которые хранили в себе данные из xml и умели загружаться и сохраняться в него. Всё на умных указателях. Работать стало удобнее за счет того, что нам нужно было строго ограниченное число типов данных внутри xml (object, string, int, float, bool, wstring, data). Вот кусок такого файла:

<object name = "Second_Turret_155_Yamato">
<integer name = "Country" value = "2"/>
<string name = "Type" value = "Gun"/>
<boolean name = "Production" value = "false"/>
<float name = "Weight" value = "177"/>
</object>

Вот работа с ним:


for (CompoundObject::ConstIterator i = turrets->begin(),
iend = turrets->end();
i != iend;
++i
)
{
std::string name = i->first; // "Second_Turret_155_Yamato"
ObjectAttribute turret = i->second;

IntegerAttibute attrCountryId = turret->get("Country");
int attrCountryId = attrCountryId->getValue();

std::string turretType = turret->getAs<TypeId::String>("Gun")->getValue();

bool production = safeGetValue(turret, "Production", false);

Attribute attrWeight = turret->get("Weight");
double weight = As<TypeId::Float>(attrWeight)->getValue();
}


Этот файл уже имеет типизацию, которую можно проверять и выдавать Exception, если тип неправильный.
Минусом первого варианта системы SMCC было то, что она была надстройкой над TinyXml и вся загрузка и сохранение велась через нее.
Дальнейшей оптимизацией было создание своего парсера xml для нашего формата. Он легковесный и работает в несколько раз быстрее TinyXml.
Следующей мыслью было то, что у нас строго ограниченный набор типов в xml, а значит можно сделать и бинарный формат. Сделали. Получили прирост скорости парсинга xml еще в несколько раз. Например, файл сэйва занимал 50mb в xml, старый парсинг и сохранение могли занимать 10 и более секунд, а новый отрабатывает менее, чем за секунду.
Ну и недавно дошли руки до загрузки xml с помощью Loading inplace. Это вообще максимально быстрый алгоритм. Работает за счет того, что число типов ограничено.
Естественно, все форматы грузятся любым загрузчиком. Даже Loading inplace грузит обычный xml, правда медленно, т.к. сначала надо распарсить всю структуру.
Также пришлось написать утилиту, конвертирующую форматы xml в разные виды, чтобы можно было бинарные форматы конвертировать в текстовый для просмотра и редактирования, но т.к. большинство xml экспортятся из maya или базы данных, то делать это приходится нечасто.

В итоге сейчас мы имеем систему работы с xml, сочетающую в себе как плюсы бинарных файлов, так и удобство текстового xml формата.
А у вас есть такой велосипед?
Отправлено 19.03.2007 в 10:40
Отвечает на сообщение 186834
0
boost::property_tree плюс своя небольшая надстройка, чтобы конвертить безконтурный граф полиморфных объектов в текстовое дерево и обратно.
Отправлено 19.03.2007 в 10:49
Отвечает на сообщение 186835
0
Alexey Baskakov wrote:
>
> boost::property_tree плюс своя небольшая
> надстройка, чтобы конвертить безконтурный граф
> полиморфных объектов в текстовое дерево и
> обратно.


А пример такого xml файла и кода для работы с ним можно?
Отправлено 19.03.2007 в 12:28
Отвечает на сообщение 186837
0
Oleg Fedorov wrote:
> А пример такого xml файла и кода для работы с ним
> можно?


Самый простой пример (без сохранения иерархии и relationship) - конфиг:

struct Config
{
enum Domain_e
{
 DOMAIN_ART = 0
, DOMAIN_GAME_DESIGN = 1
, DOMAIN_PROGRAMMING = 2
, DOMAIN_SOUND = 3
};

std::string m_sUser;
std::string m_sPassword;
Domain_e m_eDomain;

bool m_bFileSystemFlat;
boost::filesystem::path m_sMediaPath;

int m_iAutosavePeriod; // minutes
boost::filesystem::path m_sAutosavePath;

struct Layout_c : public serialization::Layout_c < Config >
{
Layout_c()
{
Simple ( "user", &Config::m_sUser, "" );
Simple ( "password", &Config::m_sPassword, "" );
Enum ( "domain", &Config::m_eDomain, DOMAIN_GAME_DESIGN )
.Enumerator( DOMAIN_ART, "art" )
.Enumerator( DOMAIN_GAME_DESIGN, "game_design" )
.Enumerator( DOMAIN_PROGRAMMING, "programming" )
.Enumerator( DOMAIN_SOUND, "sound" )
;
Simple ( "filesystem_flat", &Config::m_bFileSystemFlat, true );
Simple ( "media_path", &Config::m_sMediaPath, "" );
Simple ( "autosave_period", &Config::m_iAutosavePeriod, 10 );
Simple ( "autosave_path", &Config::m_sAutosavePath, "" );
}
};
};

<?xml version="1.0" encoding="windows-1251"?>
<SkyStudio>
<Configuration>
<user>loyso</user>
<domain>programming</domain>
<filesystem_flat>true</filesystem_flat>
<media_path>C:/Dev/Repositories/media</media_path>
<autosave_period>2</autosave_period>
<autosave_path>C:/autosave</autosave_path>
</Configuration>
</SkyStudio>

Сериализация иерархии полиморфных объектов, в данном случае - коллекция
полиморфных объектов:

class Primitive
{
};

class PrimFloat : public Primitive
{
};

struct PrimitiveSerializer : public serialization::SerializeAbstract_T < Primitive >
{
PrimitiveSerializer()
{
RegisterType < PrimFloat > ( "float" );
RegisterType < PrimInt > ( "int" );
RegisterType < PrimBool > ( "bool" );
RegisterType < PrimVec2 > ( "vec2" );
RegisterType < PrimVec3 > ( "vec3" );
RegisterType < PrimVec4 > ( "vec4" );
RegisterType < PrimTexRect > ( "texrect" );
RegisterType < PrimColor > ( "color" );
RegisterType < PrimString > ( "string" );
RegisterType < PrimFileName > ( "filename" );
RegisterType < PrimLink > ( "link" );
RegisterType < PrimEnum > ( "enum" );
}
};

class AttributeStruct
{
...
struct Layout : public serialization::Layout_c < AttributeStruct >
{
Layout()
{
ContainerPtr( "primitives", &AttributeStruct::m_Primitives, serialization::Serializer < PrimitiveSerializer > () );
}
}
...
typedef std::list < Primitive * > Primitives_t;
Primitives_t m_Primitives;
}

в xml:

...
<primitives>
<_ type="float">
<name>yaw</name>
<min>-3.1415</min>
<max>3.1415</max>
</_>
<_ type="bool">
<name>open</name>
<default>true<default>
</_>
</primitives>

В общем, если честно то сейчас я бы не стал все это на C++ писать. И даже на C# бы не стал. Сейчас я бы DSL забабахал для описания и создания диаграмм классов и объектов. И компонентных диаграмм. Не только с целью реализации сериализации разумеется.
Отправлено 19.03.2007 в 13:12
Отвечает на сообщение 186835
0
> boost::property_tree плюс своя небольшая надстройка
Аналогично.
Отправлено 20.03.2007 в 12:34
Отвечает на сообщение 186865
0
Alexey Baskakov wrote:
>
> Самый простой пример (без сохранения иерархии и
> relationship) - конфиг:
>


А вот интересно, сколько занимает парсинг 50мб файла таким парсером?
Насколько я понял из описания в Boost, этот парсер использует либо тот же TinyXml либо свой встроенный в Boost. Думаю медленный он.

> В общем, если честно то сейчас я бы не стал все
> это на C++ писать. И даже на C# бы не стал.
> Сейчас я бы DSL забабахал для описания и создания
> диаграмм классов и объектов. И компонентных
> диаграмм. Не только с целью реализации
> сериализации разумеется.


эээ. Можно подробнее? Это будет быстрее\удобнее? И в чем именно?
Отправлено 20.03.2007 в 13:19
Отвечает на сообщение 187076
0
Oleg Fedorov wrote:

> А вот интересно, сколько занимает парсинг 50мб
> файла таким парсером?
> Насколько я понял из описания в Boost, этот
> парсер использует либо тот же TinyXml либо свой
> встроенный в Boost. Думаю медленный он.

boost.ptree может использовать четыре разных xml парсера.
один из них (pugixml) - AFAIK самый быстрый из общедоступных. ну и плюс автор ptree сейчас пишет пятый, хочет pugixml обогнать.

на 50 мб файлах тормозит совсем не парсер, там уже тупо проблемы с памятью и чисто оверхеды SCL сказываются.

А откуда такие большие файлы? в интересах распараллеливания работ и versioning 1 файл должен представлять 1 unit работы одного человека (с целью минимизировать конфликты SVN/CVS например)

Плюс я не сторонник хранить проектные данные в xml (да и любом другом каноническом текстовом формате). Бинарные файлы со схемой данных (метаданными) в начале и прозрачной структурой - вот имхо то что надо. Ну и мерджилка своя для них. Разумеется все должно работать железно и стабильно.

> эээ. Можно подробнее? Это будет быстрее\удобнее?
> И в чем именно?

Ну вот эту прослойку (описание объектов и их структуры) можно будет не писать, так как она все равно уже есть на метауровне. А сгенерить по ней код, который будет заниматься сериализацией - проще простого. И никаких томрозов с компилянием навороченных C++ шаблонов.

Впрочем, у нас все равно приведенная работа с xml только в редакторе осталась.
Отправлено 20.03.2007 в 14:46
Отвечает на сообщение 186834
0
Использовали http://www.tech-know-ware.com/lmx/
Очень хорошие впечатления. По схеме (xsd) автоматически генерится код маршалинга. Стоит денег, но не больших. Поддержка отвечала в течении 2х часов. Проблемы решались за день.
Отправлено 20.03.2007 в 15:32
Отвечает на сообщение 187116
0
Сергей Захаров wrote:
>
> Использовали http://www.tech-know-ware.com/lmx/
> Очень хорошие впечатления. По схеме (xsd)
> автоматически генерится код маршалинга. Стоит
> денег, но не больших. Поддержка отвечала в
> течении 2х часов. Проблемы решались за день.


4000USD - это небольшие деньги? Хорошо вам :)
Посмотрел их генерящийся код - страшный он, хотя не это, конечно, главное.
Мы никогда не использовали автогенерацию кода по xsd - неужели это действительно нужно и удобно? Обычно мы в нечасто вызываемых кусках кода просто берем значения из дерева атрибутов, а там, где нужна скорость, кешируем уже значения в структурах. Работает быстро, понятно и удобно.
Отправлено 20.03.2007 в 15:35
Отвечает на сообщение 187091
0
Alexey Baskakov wrote:
>
> один из них (pugixml) - AFAIK самый быстрый из
> общедоступных. ну и плюс автор ptree сейчас пишет
> пятый, хочет pugixml обогнать.


:) имхо, быстрее нашего бинарного парсера он быть не может.

>
> А откуда такие большие файлы? в интересах
> распараллеливания работ и versioning 1 файл
> должен представлять 1 unit работы одного человека
> (с целью минимизировать конфликты SVN/CVS
> например)


по 50мб получались сэйвы. Там несколько десятков тысяч юнитов может быть.

> Ну вот эту прослойку (описание объектов и их
> структуры) можно будет не писать, так как она все
> равно уже есть на метауровне. А сгенерить по ней
> код, который будет заниматься сериализацией -
> проще простого. И никаких томрозов с компилянием
> навороченных C++ шаблонов.
>


похоже на то, что писал Сергей Захаров парой постов выше?

> Впрочем, у нас все равно приведенная работа с xml
> только в редакторе осталась.


аминь :)
Отправлено 20.03.2007 в 15:53
Отвечает на сообщение 187141
0
> :) имхо, быстрее нашего бинарного парсера он быть не может.

Эээ... Не понял. xml же - не бинарный формат. Есть конечно binary xml, но на него все забили.

> по 50мб получались сэйвы. Там несколько десятков тысяч юнитов может быть.


Не понимаю этой зацикленности - зачем сейвы делать в xml...
Да и 50000/10000=5 кб на юнит. Слишком много, не иначе вы туда вообще все данные скидываете, а не только runtime-defined отличия от прототипа юнита.

> похоже на то, что писал Сергей Захаров парой постов выше?

не видел.

UPDATE: увидел. не - совсем наоборот. отличается так же, как концепция генерации кода по UML от генерации кода в DSL.
Отправлено 20.03.2007 в 16:12
Отвечает на сообщение 187152
0
Alexey Baskakov wrote:
>
> > :) имхо, быстрее нашего бинарного парсера он
> быть не может.
>
> Эээ... Не понял. xml же - не бинарный формат.
> Есть конечно binary xml, но на него все забили.


Я же писал, что у нас свой велосипед :). Есть конвертер xml-binary-xml. Для быстрой загрузки и сохранения того, что надо.

>
> > по 50мб получались сэйвы. Там несколько
> десятков тысяч юнитов может быть.
>
> Да и 50000/10000=5 кб на юнит. Слишком много, не
> иначе вы туда вообще все данные скидываете, а не
> только runtime-defined отличия от прототипа
> юнита.


5 кб в xml - не так уж и много :). Там только меняющиеся данные. Кроме того, есть в игре не только юниты, но и другие сущности. Например, формации, которых тоже тысячи, АИ-приказы, которые могут быть у каждого юнита или формации и т.п. Короче, много информации надо сохранять.

> Не понимаю этой зацикленности - зачем сейвы
> делать в xml...


На самом же деле сэйвы в текстовом виде удобнее, чем в бинарном. Их проще расширять, проще читать, проще отлаживать вначале. В конце проекта на этапе мастера они превращаются в зло, т.к. тормозят и занимают много места :).
Поэтому перед мастером я сделал хитрый финт - самые частовстречающиеся объекты сохранил в xml в бинарном виде. Это сократило размер в несколько раз и ускорило загрузку также в несколько раз.
А у вас сэйв в каком виде?

>
> > похоже на то, что писал Сергей Захаров парой
> постов выше?
> не видел.
>
> UPDATE: увидел. не - совсем наоборот. отличается
> так же, как концепция генерации кода по UML от
> генерации кода в DSL.


пошел читать про DSL...
Отправлено 20.03.2007 в 16:21
Отвечает на сообщение 187161
0
> А у вас сэйв в каком виде?

Абстрактно - тупо в бинарь скидывается POD помеченных полей объектов. Конкретно (например, в гоночках) - вообще сейва почти нет :)

Если нужен был бы versioning у save/load - сделал бы метаданные по его бинарной структуре.
Отправлено 20.03.2007 в 16:36
Отвечает на сообщение 187165
0
Alexey Baskakov wrote:
>
> > А у вас сэйв в каком виде?
>
> Абстрактно - тупо в бинарь скидывается POD
> помеченных полей объектов. Конкретно (например, в
> гоночках) - вообще сейва почти нет :)


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

>
> Если нужен был бы versioning у save/load - сделал
> бы метаданные по его бинарной структуре.


Угу, в итоге тоже к этому пришли. Но неудобно. Xml проще :).
А бинарный xml еще и достаточно быстр - сейчас сохранение игры в Стальных Монстрах на тактическом уровне занимает 1-5 секунд, причем там и стратегический уровень сохраняется и тактическая битва - огромный файл. Текстовый xml тут сильно проигрывает в скорости.
Отправлено 20.03.2007 в 22:32
Отвечает на сообщение 186834
0
Oleg Fedorov wrote:
>
> Комментарии к блогу персоны Oleg Fedorov
>
> Интересно, как сейчас в разных компаниях обстоит
> дело с работой с xml форматом? Используете или
> нет? Если да, то какие средства для
> чтения\записи? Какие именно фичи из xml
> используется?
> Есть мнение, что мы изобретали в очередной раз
> свой велосипед – хотелось бы это обсудить и
> понять, так ли это .
> Вкратце про эволюцию работы с xml у нас в Лесте
> читай в блоге...
>
>
>
> Больше в блоге...
>
> http://www.dtf.ru/blog/read.php?id=45064



Почти такой же велосипед. Проходит под аббревиатурой UD.
Отправлено 21.03.2007 в 11:16
Отвечает на сообщение 187138
0
> 4000USD - это небольшие деньги? Хорошо вам :)

Нет, нам плохо :) мы не можем написать такой инструмент дешевле сами. Приходится платить.

> Мы никогда не использовали автогенерацию кода по xsd
> - неужели это действительно нужно и удобно?


Главный плюс xsd - стандартность. А это - инструменты и документация (куча книг и туториалов).

Кодогенерация по xsd позволяет делать очень оптимизированные парсеры под конкретную схему (теоретически, т.к. лично я не проверял перформанс lmx).

Из мелких приятностей - в xsd очень удобно прописывать constraints и default values. На простейшей валидации можно сэкономить.
Отправлено 21.03.2007 в 11:58
Отвечает на сообщение 187380
0
Сергей Захаров wrote:
>
> > 4000USD - это небольшие деньги? Хорошо вам :)
>
> Нет, нам плохо :) мы не можем написать такой
> инструмент дешевле сами. Приходится платить.


Честно говоря, я тоже не уверен, что у нас вышло дешевле :(.


> Из мелких приятностей - в xsd очень удобно
> прописывать constraints и default values. На
> простейшей валидации можно сэкономить.


Да, это приятная фича.
Comments.blogs
Списки доступа
  • Подписчики [789]
Права доступа
У обсуждений в этой группе различные ограничения доступа.
Пользователи имеют персональные права доступа к обсуждениям.
Показывать
сообщений
на страницу

Copyright © 2021 ООО "ДТФ.РУ". Все права защищены.

Воспроизведение материалов или их частей в любом виде и форме без письменного согласия запрещено.

Замечания и предложения отправляйте через форму обратной связи.

Пользовательское соглашение