AutoCAD .NET API: Исследование возможностей расширенных данных (XData)

Автор Тема: AutoCAD .NET API: Исследование возможностей расширенных данных (XData)  (Прочитано 37442 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Описание задачи.

Как известно, XData имеют ограничение по объёму записываемой информации в 16 КБайт. В AutoLISP и ObjectARX API есть даже специальные инструменты для проверки свободного места в XData, тогда как в .NET API, насколько мне известно, таких инструментов нет.
Помимо этого, в XData есть ограничение на длину строки данных - 255 символов. Записать можно и больше, но первый же Audit обрежет эти данные (подробнее - тут).
Добавление 1 (14.12.2018):В чём-то похожее ограничение есть на запись вещественных чисел. API позволяет записывать и извлекать значение Double.NaN, но AUDIT считает эти данные некорректными и при проверке переписывает все эти значения на 0.0 (подробнее - тут).

Само по себе число 16 Кбайт мало о чём говорит - много это или мало? Также, для лучшего понимания, с чем имеем дело, хочется получить ответы на такие вопросы:
1. Сколько может быть зарегистрированных приложений в чертеже?
2. Как влияет длина названия приложения на занимаемый объём?
3. Как влияет длина строки данных на занимаемый объём?
4. Сколько ориентировочно данных различных приложений можно поместить в XData?
5. Сколько ориентировочно данных одного приложения можно поместить в XData?

Условия и используемые инструменты

Платформа: AutoCAD Civil 3D 2014 как AutoCAD (x64)
Объект, в который записываются данные: отрезок, окружность или любой другой простой графический объект. Объект создавался каждый раз непосредственно перед запуском команды записи данных.
Типы записываемых данных: строка, целое и вещественное число.
Используемый код:
Извините, вам запрещён просмотр содержимого спойлеров.

Для проверки записанных данных использовался инструмент ARXDBG: http://adn-cis.org/forum/index.php?topic=7274.0

Результаты исследования.

1. Сколько может быть зарегистрированных приложений в чертеже?
Миллион приложений команда зарегистрировала без ошибок. Правда, при попытке посмотреть данные по базе, AutoCAD завис намертво. При 10000 приложений удалось посмотреть данные в базе:


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

2. Как влияет длина названия приложения на занимаемый XData объём?
Название приложения - 8 символов, строка данных – 1 символ. В XData поместилось 2047 записей:

Название приложения – 255 символов, строка данных – 1 символ. В XData поместилось снова 2047 записей:

Вывод: Длина названия приложения не влияет на размер XData.

3. Как влияет длина строки данных на занимаемый XData объём?
Если строка данных имеет длину 1 символ, то в XData помещается 2047 записей:

Если длину строки данных увеличить до 255 – только 31:

А может быть, если записать строки в рамках одного приложения, то получится их больше уместить? Ничего подобного:

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

4. Сколько ориентировочно данных различных приложений можно поместить в XData?
Записываются следующие данные: строка длиной 20 символов, вещественное число и целое число. Числа для каждой записи выбираются случайным образом. Это позволит косвенно оценить: будут ли различаться размеры данных в зависимости от различных значений чисел? В результате, было выполнено 273 записи:


При повторных проверках результат не менялся.
Вывод: при небольшом объёме записываемых данных, вместимость XData довольно большая – места хватает для размещения данных 200-300 приложений.
Дополнительный вывод: при различных числовых значениях размер данных не меняется.

5. Сколько ориентировочно данных одного приложения можно поместить в XData?
С теми же данными, что и в предыдущем тесте, циклов записи получилось больше - 287:

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

Общий вывод

XData действительно имеют ощутимый лимит по объёму записываемых данных. Особенно, если записываемые данные содержат строки большой длины. Если же записывать небольшой объём данных, то места может хватить на пару сотен записей.
« Последнее редактирование: 14-12-2018, 14:01:30 от Дмитрий Загорулькин »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Отличное исследование!
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
В AutoLISP и ObjectARX API есть даже специальные инструменты для проверки свободного места в XData, тогда как в .NET API, насколько мне известно, таких инструментов нет.
Можно при необходимости воспользоваться P/Invoke для acdbXdRoom и acdbXdSize.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Спасибо!
Можно при необходимости воспользоваться P/Invoke для acdbXdRoom и acdbXdSize.
Я вот как раз раздумываю: а есть ли такая необходимость? Смысл проверять текущий размер XData - быть уверенным, что данные поместятся. Так ведь, если возникает исключение eXDataSizeExceeded, то уже понятно, что данные не помещаются. Или в чём-то другом есть смысл использования этих методов? Мне пока в голову не пришла ни одна такая ситуация, где они бы понадобились.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Так ведь, если возникает исключение eXDataSizeExceeded, то уже понятно, что данные не помещаются.
Обработка исключений в .NET - это достаточно ресурсоёмкая операция, требующая еще и временных затрат. Впрочем не уверен, что использование P/Invoke для acdbXdRoom и acdbXdSize даст прирост скорости.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Я, честно говоря, пока что даже не знаю, что делать, если данные не будут помещаться :)
Была надежда на то, что этого никогда не случится. В принципе, шанс такой есть - если другие приложения не будут писать свои данные в XData нужного мне объекта, а если будут, то не кучу строк максимальной длины... Но, не исключаю, что эти если не выполнятся однажды. И вот как тогда быть? То ли просто уведомлять пользователя: "Не могу записать данные", но тогда надо предложить какой-то альтернативный вариант. А вот какой? "А давайте удалим другие данные из объекта? [Да/Нет/Мневсёравно]"? :)

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
И вот как тогда быть? То ли просто уведомлять пользователя: "Не могу записать данные", но тогда надо предложить какой-то альтернативный вариант. А вот какой? "А давайте удалим другие данные из объекта? [Да/Нет/Мневсёравно]"? :)
Тут следует учесть, что эти данные могут быть данными AutoCAD (например, размерные данные) и их крайне нежелательно удалять...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1116
  • Карма: 173
Мне кажется, что будет проще и надежнее использовать словарные записи. Могу и ошибаться :)
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Столкнулся с тем, что не надёжнее :(
Подробности - тут (Материальчик специфический): http://adn-cis.org/forum/index.php?topic=816.msg29255#msg29255
Беда в том, что словарь является отдельным объектом базы данных чертежа, поэтому, гораздо легче "теряется". В то время как XData хранятся внутри объекта и "потерять" их сложнее. Но вот это ограничение по объёму немного напрягает, конечно.

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1116
  • Карма: 173
Может, это баг самого Civil? Я сколько ни использовал подобное, ни разу не ловил потери словарных данных :( Может быть, конечно, я настолько далеко и глубоко не влезал...
Кстати, в чистом ACAD подобное повторяется?
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Может, это баг самого Civil?
Практически на 100% уверен, что это баг. Отправил запрос в DevHelp, посмотрим, что скажут.
Я сколько ни использовал подобное, ни разу не ловил потери словарных данных
Я вот тоже до недавнего времени не сомневался в надёжности словарей...
Кстати, в чистом ACAD подобное повторяется?
В чистом автокаде такое не повторить, потому что проблемы возникают при использовании механизма сивила под названием "быстрая ссылка" и соответствующей команды синхронизации таких быстрых ссылок. В автокаде такого нет. Ближайший аналог в чистом автокаде - внешняя ссылка. В принципе, можно проверить, как будут вести себя словари объектов из внешней ссылки при вставке и обновлении. Думаю, что не будет таких проблем.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
И снова здравствуйте!
Называется: "дошло до утки на третьи сутки"...
Озаботился проблемой сохранения данных других приложений в XData при записи/перезаписи моих данных. Сделал громоздкую обработку всех данных в XData "до" и "после" моих данных, чтобы затем сформировать один общий ResultBuffer и передать его в XData. А сейчас с удивлением для себя обнаружил, что API "всё делает за нас". Оказывается, что при присвоении значения XData не происходит его полная замена! Вроде бы, ожидается именно такое поведение, когда видишь присвоение значения свойству XData (7-я строка):
Код - C# [Выбрать]
  1. using (ResultBuffer rb = new ResultBuffer(new TypedValue(1001, appName)))
  2. {
  3.     foreach (TypedValue tVal in values)
  4.     {
  5.         rb.Add(tVal);
  6.     }
  7.     obj.XData = rb;
  8. }
  9.  
Однако, записываются/перезаписываются только данные приложения appName. Существующие данные других приложений сохраняются! Крайне неочевидным оказалось для меня такое поведение. Хотя, должен был раньше догадаться. Если бы это было не так, моё исследование споткнулось бы на постоянной перезаписи данных :)
Логично было бы, наверное, делать это с помощью вспомогательного метода SetXDataForApplication (по аналогии с имеющимся GetXDataForApplication). Тогда бы не возникло такого недопонимания, по крайней мере у меня. И что самое печальное - в справке об этом ни слова...

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Однако, записываются/перезаписываются только данные приложения appName.
Более того. Они и удаляются таким же образом. Т.е. если тебе нужно из Xdata удалить приложение appName, то удалять следует так:
Код - C# [Выбрать]
  1. using (ResultBuffer rb = new ResultBuffer(new TypedValue(1001, appName)))
  2. {
  3.     obj.XData = rb;
  4. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 738
Это же надо так придумать! Ну ладно, придумать... Но хотя бы задокументировали столь неочевидное поведение! Сразу вспоминается цитата с баша: http://bash.im/quote/409943
Я надеюсь, хотя бы, что если null задать, то это удалит все данные у объекта? :)

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13886
  • Карма: 1788
  • Рыцарь ObjectARX
  • Skype: rivilis
Я надеюсь, хотя бы, что если null задать, то это удалит все данные у объекта? :)
Нет. И не надейся. :) Чтобы удалить все расширенные данные объекта нужно найти все приложения, которые есть в объекте и для каждого из этих приложений выполнить удаление, как я писал выше.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение