В практике разработки на платформе 1С:Предприятие 8.3 (особенно при работе с Обычными формами в конфигурациях вроде УТ 10.3) программисты иногда сталкиваются с парадоксальной ситуацией: карточка объекта (например, справочника Номенклатура) начинает открываться крайне медленно — от 3 до 30 секунд. При этом замер производительности не показывает никаких задержек в программном коде, а ПолучитьОбъект() на сервере отрабатывает мгновенно. В этой статье мы разберем, почему наличие большого количества UUID (уникальных идентификаторов) в текстовых реквизитах может «повесить» интерфейс, и как это исправить.
Рассмотрим ситуацию, описанную разработчиком. В справочнике создано несколько текстовых реквизитов неограниченной длины. В них программно или вручную записываются списки UUID других объектов, разделенные точкой с запятой или пробелом. Типичный пример такого содержимого:
9ea51bc9-5d87-11e2-b199-902b346f5219; b56b8ed6-f673-11e5-b979-d850e6bf91f5...
Проблема проявляется следующим образом:
Выясним причину такого странного поведения платформы.
Проанализируем техническую сторону вопроса. Многие ошибочно полагают, что платформа 1С пытается «распознать» UUID в тексте и найти соответствующие им объекты в базе данных. Однако это не так. Причина кроется в алгоритме отрисовки текста в операционной системе Windows, который использует платформа для Обычных форм.
Когда у элемента управления ПолеВвода включены свойства МногострочныйРежим и Автоперенос (AutoWrap), движок отрисовки при открытии формы должен рассчитать высоту поля и расставить точки разрыва строк. Для этого он анализирует каждый символ в строке, пытаясь найти подходящие места для переноса.
Символ дефиса (-), который в избытке присутствует в каждом UUID, воспринимается алгоритмом как «мягкий перенос» (soft hyphen). Если в поле записано несколько сотен UUID, количество потенциальных точек переноса исчисляется тысячами. Алгоритм расчета геометрических параметров текста начинает работать с квадратичной сложностью. В версиях платформы 8.3.15 и 8.3.16 эта проблема обострилась из-за изменений в механизмах поддержки высокого DPI и обновленного взаимодействия с графической подсистемой Windows (GDI/Uniscribe).
Существует несколько способов устранить задержку открытия формы, не отказываясь от хранения необходимых данных.
Это самый простой и быстрый способ. Если вам не критично, чтобы длинная строка UUID красиво переносилась по краям поля, просто отключите расчет переносов. Посмотрим на свойства элемента формы:
ПолеВвода.После этого платформа перестанет вычислять точки разрыва строки по дефисам, и форма будет открываться мгновенно, так как текст будет отрисован одной длинной лентой (с использованием горизонтальной прокрутки, если она включена).
Если вам все же необходимо отображать UUID списком и обеспечивать их визуальное удобство, можно заменить стандартное текстовое поле на ПолеHTMLДокумента. Движки рендеринга HTML (даже старый IE, используемый в ОФ) гораздо эффективнее работают с длинными строками, чем стандартные контролы Windows. Рассмотрим пример заполнения такого поля:
// В процедуре ПриОткрытии или при чтении данных
ТекстДляВывода = СтрЗаменить(Объект.ДополнительныеУиды, ";", "; ");
ЭлементыФормы.ПолеHTML.УстановитьТекст("<html><body><p style='word-break: break-all;'>" + ТекстДляВывода + "</p></body></html>");
Использование CSS-свойства word-break позволит браузерному движку корректно переносить строку без тех вычислительных затрат, которые требуются стандартному полю 1С.
С точки зрения архитектуры 1С, хранение огромных списков идентификаторов внутри одной текстовой строки (особенно неограниченной длины) — не самое удачное решение. Это замедляет чтение самого объекта и увеличивает объем данных, передаваемых между клиентом и сервером. Проанализируем вариант оптимизации через Регистр Сведений.
Вместо реквизита типа Строка создайте подчиненный регистр сведений:
ОбъектСсылка (тип Ссылка на ваш справочник).ИдентификаторОбъекта (тип УникальныйИдентификатор или Строка(36)).При таком подходе вы сможете:
ТабличноеПоле.Если вы не можете изменить структуру данных или настройки поля, можно попробовать «обмануть» алгоритм переноса. Проанализируем ситуацию: если алгоритм спотыкается о дефисы, мы можем заменить их на похожие символы или добавить пробелы в критических местах.
// Пример замены символов перед выводом на форму
ДанныеДляПоля = СтрЗаменить(СсылкаНаОбъект.ТекстовыйРеквизит, "-", " "); // Заменяем дефис на пробел
// Или добавляем неразрывный пробел после каждого UUID
ДанныеДляПоля = СтрЗаменить(ДанныеДляПоля, ";", ";" + Символы.НПП);
Однако стоит помнить, что при сохранении данных из такого поля обратно в базу, вам придется делать обратную замену, что усложняет код и повышает риск возникновения ошибок в данных.
Мы выяснили, что «тормоза» при открытии форм с UUID — это чисто визуальная проблема, связанная с избыточностью символов-разделителей в многострочных полях с включенным автопереносом. Программисту при проектировании подобных интерфейсов следует придерживаться следующих правил:
ПолеВвода всегда отключайте Автоперенос.Таким образом, простое снятие одного флажка в свойствах элемента формы может сэкономить пользователям десятки минут рабочего времени в день, избавляя их от ожидания отрисовки карточек товаров или документов.