Ускорение пересчета заказа покупателя УНФ
У клиента в счете на оплату и заказе клиента при смене процента скидки пересчитывался документ. При этом счет пересчитывался быстро, а заказ — медленно. Обычно там документы состоят из нескольких сотен строк.
Поиск узких мест выявил, что торможение вызывает вот этот код:
&НаКлиенте Процедура ОбработатьТаблицу(ИмяТЧ) ... Для каждого Строка Из ИзменяемыеСтроки Цикл РассчитатьСуммуВСтрокеТабличнойЧасти(, Строка); КонецЦикла; ... КонецПроцедуры &НаКлиенте &После("РассчитатьСуммуВСтрокеТабличнойЧасти") Процедура ТР_РассчитатьСуммуВСтрокеТабличнойЧасти(ИмяТабличнойЧасти, СтрокаТабличнойЧасти, ПараметрыРасчета) ПересчитатьВесИОбъем(СтрокаТабличнойЧасти); КонецПроцедуры &НаКлиенте Процедура ПересчитатьВесИОбъем(СтрокаТабличнойЧасти) Если Не СтрокаТабличнойЧасти.Характеристика.Пустая() Тогда СтрокаТабличнойЧасти.Вес = СтрокаТабличнойЧасти.Количество * ПолучитьВесТекСтроки(СтрокаТабличнойЧасти.Характеристика); СтрокаТабличнойЧасти.Объем = СтрокаТабличнойЧасти.Количество * ПолучитьОбъемТекСтроки(СтрокаТабличнойЧасти.Характеристика); СтрокаТабличнойЧасти.Площадь= СтрокаТабличнойЧасти.Количество * ПолучитьПлощадьТекСтроки(СтрокаТабличнойЧасти.Характеристика); Возврат; КонецЕсли; СтрокаТабличнойЧасти.Вес = СтрокаТабличнойЧасти.Количество*ВернутьВес(СтрокаТабличнойЧасти.Номенклатура); СтрокаТабличнойЧасти.Объем = СтрокаТабличнойЧасти.Количество*ВернутьОбъем(СтрокаТабличнойЧасти.Номенклатура); КонецПроцедуры
При пересчете веса и объема вызывались серверные функции ВернутьВес и ВернутьОбъем. Т.е. постоянно дергался клиент-сервер.
Я поменял вызов следующим образом:
&НаКлиенте Перем дор_СтрокиПересчета; &НаКлиенте &После("РассчитатьСуммуВСтрокеТабличнойЧасти") Процедура ТР_РассчитатьСуммуВСтрокеТабличнойЧасти(ИмяТабличнойЧасти, СтрокаТабличнойЧасти, ПараметрыРасчета) //Откладываем пересчет дор_СтрокиПересчета.Добавить(СтрокаТабличнойЧасти.ПолучитьИдентификатор()); ПодключитьОбработчикОжидания("ТР_ОтложенныйПересчет", 0.1, истина); //ПересчитатьВесИОбъем(СтрокаТабличнойЧасти); КонецПроцедуры &НаКлиенте Процедура ТР_ПриОткрытииПеред(Отказ) дор_СтрокиПересчета = Новый Массив(); КонецПроцедуры &НаКлиенте Процедура ТР_ОтложенныйПересчет() Экспорт Если дор_СтрокиПересчета.Количество() > 0 Тогда ТР_ОтложенныйПересчетНаСервере(дор_СтрокиПересчета); КонецЕсли; КонецПроцедуры &НаСервере Процедура ТР_ОтложенныйПересчетНаСервере(дор_СтрокиПересчета) Экспорт Для Каждого ИдентификаторСтроки ИЗ дор_СтрокиПересчета Цикл СтрокаТабличнойЧасти = Объект.Запасы.НайтиПоИдентификатору(ИдентификаторСтроки); Если СтрокаТабличнойЧасти <> Неопределено Тогда ПересчитатьВесИОбъемНаСервере(СтрокаТабличнойЧасти); КонецЕсли; КонецЦикла; КонецПроцедуры &НаСервере Процедура ПересчитатьВесИОбъемНаСервере(СтрокаТабличнойЧасти) //Скопирована из клиентской процедуры Если Не СтрокаТабличнойЧасти.Характеристика.Пустая() Тогда СтрокаТабличнойЧасти.Вес = СтрокаТабличнойЧасти.Количество * ПолучитьВесТекСтроки(СтрокаТабличнойЧасти.Характеристика); СтрокаТабличнойЧасти.Объем = СтрокаТабличнойЧасти.Количество * ПолучитьОбъемТекСтроки(СтрокаТабличнойЧасти.Характеристика); СтрокаТабличнойЧасти.Площадь= СтрокаТабличнойЧасти.Количество * ПолучитьПлощадьТекСтроки(СтрокаТабличнойЧасти.Характеристика); Возврат; КонецЕсли; СтрокаТабличнойЧасти.Вес = СтрокаТабличнойЧасти.Количество*ВернутьВес(СтрокаТабличнойЧасти.Номенклатура); СтрокаТабличнойЧасти.Объем = СтрокаТабличнойЧасти.Количество*ВернутьОбъем(СтрокаТабличнойЧасти.Номенклатура); КонецПроцедуры
Пришлось клонировать функцию ПересчитатьВесИОбъем. Узнал, что если несколько раз подключить один и тот же обработчик ожидания, он вызовется все равно один раз, что и требовалось.
Стало работать быстрее, но я поставил замер производительности до входа в свой обработчик ожидания и заметил, что все же некоторые серверные вызовы происходят. Поэтому работает не идеально быстро. Вообще, сделали бы весь пересчет на сервере, тогда можно было бы оптимизировать, а так приходится идти на компромисссы.
Среда: УНФ 1.6.26.172. Объем: 1 час.
Свежие комментарии