Ускорение медленной работы строк в 1С на примере 1С:Документооборот КОРП

02.10.20

База данных - HighLoad оптимизация

Если у вас в 1С:Документооборот КОРП 2.1.11.5 (часть более старых и новых конфигураций): 1) Долго отправляется почта в формате HTML; 2) Медленно открывается документы внутренние / входящие / исходящие; 3) Тормозит область просмотра или открытие задач. Тогда вам сюда.

Типовые конфигурации 1С умеют показать - как делать не надо.

Что может быть опасного в выражениях работы со строками или символами, например:

Строка = Строка + Символ;
КодСимвола(Строка, Позиция);
Символ = Символ(Код);

Пусть даже это происходит в цикле, ведь одна операция выполняется 0,5-2 миллисекунды.

Допустим, в такой типовой функции, которая часто используется в различных блоках конфигурации.

Функция ЗаменитьСпецСимволыHTML(Строка, СпецСимволыСоотв = Неопределено) Экспорт
	СоответствиеСпецСимволов = РаботаС_HTMLПовтИсп.ПолучитьСоответствиеСпецСимволов();
	ЗаменитьСпецСимволHTML(Строка, 38, "amp");
	НоваяСтрока = "";
	
	Для Поз = 1 По СтрДлина(Строка) Цикл
		Код = КодСимвола(Строка, Поз);
		ИмяСимвола = СоответствиеСпецСимволов.Получить(Код);
		
		Если ИмяСимвола = Неопределено Тогда
			НоваяСтрока = НоваяСтрока + Символ(Код);
		Иначе
			НоваяСтрока = НоваяСтрока + "&" + ИмяСимвола + ";";
		КонецЕсли;
	КонецЦикла;

	Строка = НоваяСтрока;
	Возврат Строка;
КонецФункции

Но если длина строки измеряется тысячами и десятками тысячами символов, то несложно догадаться, что это займет уже секунды,  десятки секунд, а может даже и сотни, что у нас и случилось.

Кажется, надо срочно выбрать другой тип переменной, отличный от строки, или использовать другие механизмы и объекты.

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

  1. Получаем "код символа".
  2. Ищем "имя символа" в соответствии.
  3. Добавить к строке символ, если "имя символа":
    1. тогда добавить "символ" по коду символа;
    2. иначе добавить "имя символа".

Вроде все логично, проверяем символы и если необходимо, производим замену.

Но вот идеи, что можно сделать:

  1. Зачем переводить символ в код и обратно пункты 1. и 3.1., надо получать символ, а от него код, тогда не надо получать символ по коду.
  2. Сделать КЭШ в котором хранились символы, по которым была выполнена проверка и результат поиска.
  3. Пункт 3.1 будет выполнять подряд несколько раз, если не было спец. символов, значит надо накапливать строку и добавлять целиком, а не по одному символу. 

Посмотрим, что у нас получилось

Функция ЗаменитьСпецСимволыHTML(Строка, СпецСимволыСоотв = Неопределено) Экспорт
	
	СоответствиеСпецСимволов = РаботаС_HTMLПовтИсп.ПолучитьСоответствиеСпецСимволов();
	ЗаменитьСпецСимволHTML(Строка, 38, "amp");
	НоваяСтрока = "";
	
	// {{ новый алгоритм
	КЭШ_Символов = Новый Соответствие;
	Последний = 0;

	Для Поз = 1 По СтрДлина(Строка) Цикл
		Символ = Сред(Строка, Поз, 1);
		ИмяСимвола = КЭШ_Символов.Получить(Символ);
		
		Если ИмяСимвола = Неопределено Тогда 
			Код = КодСимвола(Строка, Поз);
			ИмяСимвола = СоответствиеСпецСимволов.Получить(Код);
			
			Если ИмяСимвола = Неопределено Тогда
				ИмяСимвола = "Неопределено";
			КонецЕсли;
			
			КЭШ_Символов.Вставить(Символ, ИмяСимвола);
		КонецЕсли;
			
		Если ИмяСимвола <> "Неопределено" Тогда 
			Если Последний = 0 Тогда 
				ПодСтрока = "";
			Иначе 
				ПодСтрока = Сред(Строка, Последний, Поз - Последний);
				Последний = 0;
			КонецЕсли;
			
			НоваяСтрока = НоваяСтрока + ПодСтрока + "&" + ИмяСимвола + ";";
		ИначеЕсли Последний = 0 Тогда 
			Последний = Поз;
		КонецЕсли;
	КонецЦикла;
	
	Строка = НоваяСтрока + ?(Последний = 0, "", Сред(Строка, Последний, Поз - Последний + 1));
	// }} новый алгоритм
	
	Возврат Строка;
КонецФункции

Давайте посмотрим, как изменился замер производительности

О чудо стало работать почти в 100 раз быстрее.

 

PS: Часто программисты не пытаются решить проблемы логики, а пытаются решить проблему медленных механизмов.

Но как показывает практика - исправление логики приносит более значимый результат.

 

Update (2020-10-02 15:15):

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

В типовом релизе 1С:Документооброт ПРОФ 2.0.14.4 используют процедуру "ЗаменитьСпецСимволHTML()", но с ней есть проблема.

Значение символа по коду "Символ(КодСимвола)" вычисляется долго.

Но кто нам мешает объединить все лучшее в одном месте.

Функция ЗаменитьСпецСимволыHTML(Строка, СпецСимволыСоотв = Неопределено) Экспорт
	СоответствиеСпецСимволов = РаботаС_HTMLПовтИсп.ПолучитьСоответствиеСпецСимволов();
	ЗаменитьСпецСимволHTML(Строка, 38, "amp");
	
	// {{ новый алгоритм (4)
	Для Каждого СпецСимвол Из СоответствиеСпецСимволов Цикл 
		Строка = СтрЗаменить(Строка, РаботаС_HTMLПовтИсп.ПолучитьСимволПоКоду(СпецСимвол.Ключ), "&" + СпецСимвол.Значение + ";");
	КонецЦикла;
	// }} новый алгоритм (4)
	
	Возврат Строка;
КонецФункции

и в общем в подходящем общем модуле, добавил функцию для повторного использования.

Функция ПолучитьСимволПоКоду(Код) Экспорт
	Возврат Символ(Код);
КонецФункции

Итого: При первом использовании время немного больше 1 сек, но при повторном использовании время падает до 0,05 сек!

Вступайте в нашу телеграмм-группу Инфостарт

Долго Медленно Тормозит УСКОРЕНИЕ Оптимизация Документооброт Строка HTML доработка типовых КОРП избыточное

См. также

HighLoad оптимизация Программист 1C:ERP Бесплатно (free)

Использование оператора «В» для полей или данных составного типа (например, Регистратор) может приводить к неочевидным проблемам.

10.11.2025    5024    ivanov660    48    

50

HighLoad оптимизация Программист 1С:Предприятие 8 1C:ERP Бесплатно (free)

Приведем примеры использования различных в динамических списках и посмотрим, почему это плохо.

18.02.2025    7973    ivanov660    39    

61

HighLoad оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    10413    ivanov660    13    

64

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.

06.06.2024    16382    Evg-Lylyk    73    

46

HighLoad оптимизация Программист 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    8042    spyke    29    

54

HighLoad оптимизация Программист 1С:Предприятие 8 Бесплатно (free)

Оказывается, в типовых конфигурациях 1С есть, что улучшить!

13.03.2024    11340    vasilev2015    22    

47
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. gabrielyants 38 01.10.20 23:36 Сейчас в теме
Спасибо за статью, неплохой вариант решения проблемы!
Sla; pro96inf; karpik666; BuildSolution; +4 Ответить
2. Sedaiko 602 02.10.20 09:39 Сейчас в теме
Должно еще ускорится если заменить
НоваяСтрока = НоваяСтрока + ПодСтрока + "&" + ИмяСимвола + ";";
на
МассивНовыхСтрок.Добавить(ПодСтрока + "&" + ИмяСимвола + ";")
и в и после уже соединить
НоваяСтрока=СтрСоединить(МассивНовыхСтрок,"")

СтрСоединить специально для этого и ввели, чтобы ускорить конкатенацию
Поручик; simonovich; cosmo2004; +3 Ответить
5. Iaskeliainen 397 02.10.20 14:24 Сейчас в теме
(2) Проверил данный вариант, получилось выиграть еще 1/3 времени. То есть за 0,6 сек.
Далее можно углубиться в повторное использование
	// {{ новый алгоритм (2)
	КЭШ_Символов = Новый Соответствие;
	Последний = 0;
	МассивНовыхСтрок = Новый Массив;

	Для Поз = 1 По СтрДлина(Строка) Цикл
		Символ = Сред(Строка, Поз, 1);
		ИмяСимвола = КЭШ_Символов.Получить(Символ);
		
		Если ИмяСимвола = Неопределено Тогда 
			Код = КодСимвола(Строка, Поз);
			ИмяСимвола = СоответствиеСпецСимволов.Получить(Код);
			
			Если ИмяСимвола = Неопределено Тогда
				ИмяСимвола = "Неопределено";
			КонецЕсли;
			
			КЭШ_Символов.Вставить(Символ, ИмяСимвола);
		КонецЕсли;
			
		Если ИмяСимвола <> "Неопределено" Тогда 
			Если Последний = 0 Тогда 
				ПодСтрока = "";
			Иначе 
				ПодСтрока = Сред(Строка, Последний, Поз - Последний);
				Последний = 0;
			КонецЕсли;
			
			МассивНовыхСтрок.Добавить(ПодСтрока + "&" + ИмяСимвола + ";");
		ИначеЕсли Последний = 0 Тогда 
			Последний = Поз;
		КонецЕсли;
	КонецЦикла;
	
	Если Последний <> 0 Тогда 
		МассивНовыхСтрок.Добавить(Сред(Строка, Последний, Поз - Последний + 1) + "&" + ИмяСимвола + ";");
	КонецЕсли;
	
	Строка = СтрСоединить(МассивНовыхСтрок, "");
	// }} новый алгоритм (2)
Показать
Mechanist; +1 Ответить
6. Iaskeliainen 397 02.10.20 14:53 Сейчас в теме
(5) добавил повторное использование, перенес
КодСимвола(Строка, Поз)
в модуль
РаботаС_HTMLПовтИсп


Получилось ускорить еще в 2 раза, до 0,35 сек.
3. Yashazz 4890 02.10.20 11:38 Сейчас в теме
Вещи-то в целом очевидные, но за эти две фразы
Часто программисты не пытаются решить проблемы логики, а пытаются решить проблему медленных механизмов

Типовые конфигурации 1С умеют показать - как делать не надо

респект однозначно.
zabaluev; Iaskeliainen; +2 Ответить
4. Iaskeliainen 397 02.10.20 13:55 Сейчас в теме
Коллеги подсказали, что в 1С:Документооброт ПРОФ 2.0.14.4 используется
Процедура ЗаменитьСпецСимволHTML(Строка, КодСимвола, ИмяСимвола)
	
	Строка = СтрЗаменить(Строка, Символ(КодСимвола), "&" + ИмяСимвола + ";");
	
КонецПроцедуры

организовал, через неё
	Для Каждого СпецСимвол Из СоответствиеСпецСимволов Цикл 
		ЗаменитьСпецСимволHTML(Строка, СпецСимвол.Ключ, СпецСимвол.Значение);
	КонецЦикла;

Время выросло на 10%, до 1 сек
8. Iaskeliainen 397 02.10.20 15:08 Сейчас в теме
(4) Добавление повторного использования
Символ(КодСимвола)

Добавила скорости до космических 0,05 сек.
Надо добавить в статью.
Mechanist; +1 Ответить
9. Iaskeliainen 397 02.10.20 15:30 Сейчас в теме
(4) Ждем этот вариант в типовой конфигурации :-)
7. protexprotex 141 02.10.20 14:56 Сейчас в теме
Да. Правильно. Проблема зачастую лежит в плоскости кривизны рук, а не в проблеме "железо не тянет" :-)
10. BobNN 02.10.20 22:42 Сейчас в теме
(7)
Любые курсы программирования должны предваряться курсами программирования на программируемом калькуляторе.
(С) идея чур моя!!
11. nomad_irk 82 02.10.20 23:13 Сейчас в теме
(10) ....с замером производительности и мониторингом утилизации аппаратной части :)
12. FatPanzer 02.10.20 23:35 Сейчас в теме
(10) Да я как раз и начинал с МК-52...
13. protexprotex 141 03.10.20 08:59 Сейчас в теме
(10) Точно! Наш препод говорил - учу Вас программировать на ассемблере потому, что он развивает логическое мышление и главное развивает привычку оптимизировать код еще в момент его написания, а не потом когда код уже написан и работает медленно и чтобы его оптимизировать нужно все переписать.
14. SlavaKron 05.10.20 08:27 Сейчас в теме
(13) А еще есть мнение, что Преждевременная оптимизация — корень всех (или большинства) проблем в программировании.
athena; Tyler Durden; +2 Ответить
15. protexprotex 141 05.10.20 10:13 Сейчас в теме
(14) Это да. Согласен. Но и ваять а кагбы вышло - лишь бы работало - тоже не айс. Потом чтобы переделать структуру программы - лучше заново все переписать. в 1С это не так критично. А вот, например программа на c++ (или еще хуже на ассемблере) - там нет априори заданных объектов типа ТаблицаЗначений, СписокЗначений (STL - компоненты не в счет - они все же более узкоспециализированные) - там структуру не ту выбереш - и потом чтобы все это оптимизировать, то легче заново переписать. Все должно быть в меру.
16. ICeZm 23 12.10.20 14:20 Сейчас в теме
Для отправки сообщения требуется регистрация/авторизация