Себестоимость у нас считается достаточно долго от 30 минут и больше в зависимости от разных факторов.
Используем партионный учет. Списание партий "по средней" в БУ/НУ, по ФИФО в УУ
Как-то раз решил сделать замер производительности чтобы определить какие операции занимают много времени. Замер приложен в файле ЗамерПроведенияСебестоимости.pff.
Меня очень удивило, что почти 10% общего времени выполнялся код:
Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
Вроде бы ничего криминального, но этот код выполнялся в моем случае в двух местах в общей сложности более 159 млн раз!
Стал смотреть где и как используется структура "СтруктураСостояния" и обнаружил, что как структура-то собственно она нигде не используется. Везде используется только ее ключ. Поэтому было решено отказаться от этой структуры и перейти к массиву. Так как в коде требовалось использовать как все ключи этой струтуры, так и все кроме "ВременнаяРазница" и "ПостояннаяРазница", то решено было создать два массива.
В приложенном файле КорректировкаСтоимости_РассчитатьСписаниеПоСредней.txt находится уже готовая к применению процедура - просто замените штатную.
Для тех кто не имеет доступ к скачиванию распишу, что исправил в процедуре РассчитатьСписаниеПоСредней() из общего модуля КорректировкаСтоимости УПП 1.3.37.1 (вообще эта процедура не менялась со времен как минимум 1.2.16.1)
Для возможности сравнения времени операции в начало процедуры добавим (учитываем, что ТекущаяУниверсальнаяДатаВМиллисекундах() появилась только в 8.2.17, для более ранних используем просто ТекущаяДата())
// ША
НачалоОперации = ТекущаяУниверсальнаяДатаВМиллисекундах();
ИспользоватьМассивы = Истина;
// ША
После кода
СтруктураСостояния = Новый Структура;
Добавим
// ША
Если ИспользоватьМассивы Тогда
МассивСостояний = Новый Массив;
МассивСостоянийБР = Новый Массив;
КонецЕсли;
// ША
После кода
СтруктураСостояния.Вставить(Колонка.Имя)
Добавим
// ША
Если ИспользоватьМассивы Тогда
МассивСостояний.Добавить(Колонка.Имя);
Если Не Колонка.Имя = "ВременнаяРазница" И Не Колонка.Имя = "ПостояннаяРазница" Тогда
МассивСостоянийБР.Добавить(Колонка.Имя);
КонецЕсли;
КонецЕсли;
// ША
Код
НайденоСостояние=Истина;
Для Каждого Элемент Из СтруктураСостояния Цикл
Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
Продолжить;
КонецЕсли;
Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ]) Тогда
НайденоСостояние = Ложь; // состояния различны
Прервать; // дальше можно не проверять
КонецЕсли;
КонецЦикла;
Заменим на
НайденоСостояние=Истина;
// ША
Если ИспользоватьМассивы Тогда
Для Каждого Элемент Из МассивСостоянийБР Цикл Если ЭлементСостояние.Значение[Элемент] <> Строка[Элемент] Тогда НайденоСостояние = Ложь; Прервать; КонецЕсли; КонецЦикла;
Иначе
// ША
Для Каждого Элемент Из СтруктураСостояния Цикл
Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
Продолжить;
КонецЕсли;
Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ]) Тогда
НайденоСостояние = Ложь; // состояния различны
Прервать; // дальше можно не проверять
КонецЕсли;
КонецЦикла;
КонецЕсли; // ША
Код
// Переносим в соответствие
СтрСост = Новый Структура;
Для Каждого Элемент Из СтруктураСостояния Цикл
Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
Продолжить;
КонецЕсли;
СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ]);
КонецЦикла;
Заменим на
// Переносим в соответствие
СтрСост = Новый Структура;
// ША
Если ИспользоватьМассивы Тогда
Для Каждого Элемент Из МассивСостоянийБР Цикл СтрСост.Вставить(Элемент, Строка[Элемент]); КонецЦикла;
Иначе
// ША
Для Каждого Элемент Из СтруктураСостояния Цикл
Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
Продолжить;
КонецЕсли;
СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ]);
КонецЦикла;
КонецЕсли; // ША
Код
НайденоСостояние=Истина;
Для Каждого Элемент Из СтруктураСостояния Цикл
Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
Продолжить;
КонецЕсли;
Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]) Тогда
НайденоСостояние = Ложь; // состояния различны
Прервать; // дальше можно не проверять
КонецЕсли;
КонецЦикла;
Заменим на
НайденоСостояние=Истина;
// ША
Если ИспользоватьМассивы Тогда
Для Каждого Элемент Из МассивСостоянийБР Цикл Если ЭлементСостояние.Значение[Элемент] <> Строка[Элемент + ПрефиксПараметровНовогоСостояния] Тогда НайденоСостояние = Ложь; Прервать; КонецЕсли; КонецЦикла;
Иначе
Для Каждого Элемент Из СтруктураСостояния Цикл
Если Элемент.Ключ = "ВременнаяРазница" или Элемент.Ключ = "ПостояннаяРазница" тогда
Продолжить;
КонецЕсли;
Если НЕ (ЭлементСостояние.Значение[Элемент.Ключ] = Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]) Тогда
НайденоСостояние = Ложь; // состояния различны
Прервать; // дальше можно не проверять
КонецЕсли;
КонецЦикла;
КонецЕсли; // ША
Код
// Переносим в соответствие
СтрСост = Новый Структура;
Для Каждого Элемент Из СтруктураСостояния Цикл
СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]);
КонецЦикла;
Заменим на
// Переносим в соответствие
СтрСост = Новый Структура;
// ША
Если ИспользоватьМассивы Тогда
Для Каждого Элемент Из МассивСостояний Цикл СтрСост.Вставить(Элемент, Строка[Элемент+ПрефиксПараметровНовогоСостояния]); КонецЦикла;
Иначе
Для Каждого Элемент Из СтруктураСостояния Цикл
СтрСост.Вставить(Элемент.Ключ, Строка[Элемент.Ключ+ПрефиксПараметровНовогоСостояния]);
КонецЦикла;
КонецЕсли; // ША
Для анализа эффекта от кода будем записывать время выполнения процедуры в журнал регистрации. Для этого в конце процедуры добавим
// ША
ЗаписьЖурналаРегистрации("СписаниеПоСредней, сек", УровеньЖурналаРегистрации.Предупреждение, , ,
Формат((ТекущаяУниверсальнаяДатаВМиллисекундах() - НачалоОперации) / 1000, "ЧДЦ=3; ЧГ=0"));
// ША
Теперь меняя всего одну строку (ИспользоватьМассивы = Истина/Ложь) в модуле мы можем проверить эффект от предложенных манипуляций. В моем случае время выполнение этой процедуры сократилось примерно в два раза, что уменьшило время расчета себестоимости на величину порядка 7-10 минут. Конечно это не ускорение расчета себестоимости в разы, но неплохое начало оптимизации
Так же значительно ускорилось время проведения документа "Корректировка стоимости списания товаров"
Тестируем, отписываемся о результатах полученных на ваших базах
Отредактировано 13.03.2013
1) Указал что используем партионный учет
2) Добавил пропущенное в тексте статьи заполнение массивов (в прикрепленном файле это было)
3) Добавил, что ускорилось время проведения документа "Корректировка стоимости списания товаров"
Для раскраски кода применялась Разукрашка