Инфостарт - это профессиональное сообщество людей, занимающихся автоматизацией учета и управления с помощью программы 1С:Предприятие.

1С:Предприятие 7.7. Оптимизация.

30

Настройка и оптимизация

31.01.2009 [08.02.2009]

Описание

Разгоняем 1С:Предприятие 7.7. Выжимаем последние соки. (версия статьи 3).

Хочу сразу оговориться (уточнить), что в статье описаны приемы, которые позволяют на моем домашнем компьютере рассчитывать 11000 абонентов и при этом формировать 60000 записей в журнал расчетов за 26 секунд в монопольном режиме в DBF версии 1С:Предприятия 7.70.025 на компоненте Расчет (ОС XP). Объем базы данных около 350 Mb. Перерасчет за пол года формирует 190000 записей за 2 минуты, при этом проводится только 1 документ.

Постараюсь учесть замечания из комментариев к статье...

Мысль написать статью у меня появилась после того, как был задан вопрос в процессе обсуждения конфигурации для Абонентского отдела водоканала. Вопрос был прост: «Какие проблемы встречались, и какие методы использовались для повышения производительности».

Ответить на этот вопрос односложно не представляется возможным, т.к. было применено несколько различных приемов. Начнем с того, что я знаю только два способа, которые позволяют поднять производительность вычислительной системы:

  1. Увеличить вычислительную мощь (железо)
  2. Сократить количество выполняемых действий (программа)

С первым способом все просто. Основной прирост производительности достигается заменой существующей вычислительной системы на более современную. Достаточно мощную и сбалансированную по производительности между основными компонентами: дисковой подсистемой, памятью и процессором. Не стоит забывать о сетевом оборудовании и ОС.

По подбору оборудования есть достаточно много статей, поэтому на этом без сомнения важном способе повышения производительности задерживаться не будем, а рассмотрим поподробнее второй способ. Разумеется в свете примененных приемов в конфигурации Абонентский отдел водоканала.

Начнем с простого и очевидного приема. Использование библиотек turbobl.dll, автор Александр Орефков или 1cpp.dll. Если рассматривать типовые конфигурации фирмы 1С для 1С:Предприятия 7.7, то наиболее заметный эффект использования данных библиотек проявляется в конфигурациях «1С:Зарплата и кадры 7.7» и «1С:Комплексная конфигурация 7.7». В данном случае для использования этих библиотек не требуется значительная модификация кода конфигурации. Эффект наступает сразу после загрузки библиотек даже в типовых конфигурациях, т.к. рост производительности происходит на уровне платформы 1С:Прелприятия 7.7. В базовых версиях можно воспользоваться обработкой, которая загрузит одну из библиотек.

Например, для загрузки библиотеки можно вставить в конец глобального модуля следующий код:

ИмяБиблиотеки = КаталогПрограммы() + "TurboBL.dll";
Если ФС.
СуществуетФайл(ИмяБиблиотеки) = 1 Тогда
    ЗагрузитьВнешнююКомпоненту(ИмяБиблиотеки
);
Иначе

    ИмяБиблиотеки = КаталогИБ() + "TurboBL.dll"
;
    Если ФС.
СуществуетФайл(ИмяБиблиотеки) = 1 Тогда
        ЗагрузитьВнешнююКомпоненту(ИмяБиблиотеки
);
    КонецЕсли;
КонецЕсли;

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

Второй прием связан с сокращением общего количества точек (разименований) при выполнении кода. Этот прием является продолжением или частной модификацией первого приема. Т.е. рост производительности достигается за счет сокращения количества операций разименования.

Например:

Форма.Закладки.Добавить("Общий,Кнопки", "Общий");
Форма.Закладки.Добавить
("Льготы,Кнопки", "Льготы");
Форма.Закладки.Добавить
("Объекты,Кнопки", "Объекты");

Заменяем на

СписокЗакладок = Форма.Закладки;
СписокЗакладок.Добавить
("Общий,Кнопки", "Общий"
);
СписокЗакладок.Добавить("Льготы,Кнопки", "Льготы");

СписокЗакладок.Добавить
("Объекты,Кнопки", "Объекты");

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

Третий прием связан с сокращением количества используемых в конфигурации команд СоздатьОбъект(). Команды СоздатьОбъект("СписокЗначений") и СоздатьОбъект("ТаблицаЗначений") встречаются 1 раз только в глобальном модуле конфигурации.

Перем глПустаяТаблицаЗначений Экспорт;

//*******************************************************
//  глТипТаблицаЗначений()
//
//  Параметры:
//      нет
//
//  Возвращаемое значение:
//      Пустая таблица значений
//
//  Описание:
//      Возвращает объект типа "ТаблицаЗначений"
//      Работает в 5-6 раз быстрее чем использование
//      
конструкции
СоздатьОбъект("ТаблицаЗначений")
//
Функция глТипТаблицаЗначений()
Экспорт
    Перем
ТаблицаЗначений;

    глПустаяТаблицаЗначений.Выгрузить
(ТаблицаЗначений
);
    Возврат ТаблицаЗначений
;

КонецФункции
// глТипТаблицаЗначений

глПустаяТаблицаЗначений = СоздатьОбъект("ТаблицаЗначений");

Далее по тексту всех модулей использование вызовов может быть следующим:

Процедура ПроцедураСозданияТаблиц() 
    Перем
Таблица1, Таблица2, Таблица3;

 
    глПустаяТаблицаЗначений.Выгрузить
(Таблица1);
    Таблица1.НоваяКолонка
("ТекущийЭлемент");
    Таблица1.НоваяКолонка
("ТЗ");

    Пока <УсловиеЦикла>
Цикл
        // Запишем таблицу в таблицу таблиц

        Таблица1.НоваяСтрока
();
        Таблица1.ТекущийЭлемент
= ТекущийЭлемент;
        Таблица1.ТЗ
= глТипТаблицаЗначений();
    
КонецЦикла;

КонецПроцедуры
//глИнициализацияВидовТарифов

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

ЖУ = СоздатьОбъект("ЖурналРасчетов.Учет");
ЖР
= СоздатьОбъект("ЖурналРасчетов.Учет");

Пятый прием связан с использованием эффективных порций обрабатываемой информации. Эффективные порции могут измеряться в строках документов, количестве записей или количестве сотрудников. Эти порции чтения записи обрабатываются в транзакции. Следует отметить, что размер эффективных порций зависит от режима работы 1С:Предприятия 7.7. В монопольном режиме работы размер эффективных порций в 2-4 раза больше, чем в разделенном режиме. Это связано с обработкой блокировок, которые создают дополнительный трафик в разделенном режиме.

В этом приеме есть некоторое противоречие, потому что транзакции призваны обеспечить целостность выполняемых изменений в информационной базе. А при использовании данного приема документ проводится несколькими транзакциями. Сбой при проведении в одной из транзакций может привести к частичному проведению документа, что, конечно же, исказит картину целостности информации. К счастью таких проблем за 8 лет не возникало.

Для определения размера эффективных порций можно воспользоваться счетчиками диспетчера задач «Прочитано байт» и «Записано байт». При подборе эффективной порции уменьшение значения этих показателей чаще всего дает наибольший рост производительности.

Рассмотрим возможную реализацию данного приема чуть подробнее.

  1. Отключается автоматическое удаление движений документа
  2. В форме документа создается процедура, которая запускает на проведение документ блоками
  3. В модуле документа процедура проведения изменяется на работу с блоками данных
  4. В модуле документа добавляется процедура отмены проведения
  5. В глобальном модуле добавляются процедуры на события пометки на удаление и отмены проведения документов с "особой" обработкой документов без автоматического удаления движений
  6. Изменяется групповая обработка документов, которая для документов без автоматического удаления движений открывает форму с передачей параметра запускающего документ на проведение

Блоки могут формироваться в виде списка (списка значений, массива и т.д.) или в виде указателя: номер строки, позиция в выборке по справочнику и т.д.

Примеры реализации можно посмотреть в типовых конфигурациях 1С или здесь http://www.infostart.ru/projects/3163/

Пример обработки блоков с передачей указателя строки документа.
Текст в модуле формы документа

//*******************************************************
//  __Провести()
//
//  Параметры:
//      Нет
//
//  Описание:
//      Сохраняет и проводит документ. При этом делит процесс проведения на
//      несколько транзакций, что значительно сокращает общее время
//      проведения документа.
//

Процедура __Провести()
      
    ПриЗаписи
();
    Если СтатусВозврата() = 0 Тогда
        Возврат;
    ИначеЕсли
Модифицированность
() = 1 Тогда
        Записать();
    ИначеЕсли
Выбран
() = 0 Тогда
        Записать();
    КонецЕсли;
 
    Если
глУдалитьДвиженияДокумента(ТекущийДокумент
()) = 0 Тогда
        Возврат
    КонецЕсли;

 

    ФлагПроведения = 1;
   
Сч = 1; КоличествоСтрок = КоличествоСтрок
();
    Пока
Сч <= КоличествоСтрок
Цикл
        ФлагПроведения = Провести(,Сч
);
        Если ФлагПроведения = 0 Тогда
            Прервать
        КонецЕсли;
        Сч = Сч
+ 500;
    КонецЦикла;

    Если ФлагПроведения = 0 Тогда
       
глУдалитьДвиженияДокумента(ТекущийДокумент());
       
СделатьНеПроведенным();
    КонецЕсли;
 
КонецПроцедуры
//__Провести

Текст в модуле документа

//*******************************************************
Процедура ОбработкаПроведения(Режим = 0)
    
// Режим = 0 - провести документ без формирования движений по документу
    // Режим > 0 - допроведение документа

 
    Если ГрупповаяОбработка() = 1 Тогда
        глСообщениеГрупповойОбработки(ТекущийДокумент
);
        СтатусВозврата(0); Возврат;
    ИначеЕсли
Режим
= 0 Тогда
        Возврат;
    КонецЕсли;
 
    Для
Сч = Режим По Мин(Режим + 499, КоличествоСтрок()) Цикл
        ПолучитьСтрокуПоНомеру(Сч);
        // Текст обработки строк документа
    КонецЦикла;
 
КонецПроцедуры //ОбработкаПроведения

Шестой прием связан с заменой использования для объектов типа СписокЗначений метода Принадлежит() на метод Найти(). Это связано с особенностями данных методов. Вот описание из метода Принадлежит():

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

Седьмой прием касается передачи параметров между функциями в модуле. Довольно часто математика конфигурации развалена по функциям и процедурам. При этом одни и те же переменные передаются между функциями и процедурами по ссылкам. На передачу и прием параметров также тратяится некоторое время. Эти переменные можно объявить глобальными, если обработка происходит в глобальном модуле или объявить переменными модуля, если обработка происходит в модуле формы или модуле объекта.

Восьмой прием связан с сокращением повторных обращений к базе данных в рамках, например, проведения документа. Т.к. операции чтения из базы данных являются более медленными, чем, например, из ТаблицыЗначений.

Разумеется, в конфигурации Абонентский отдел водоканала применяется еще множество других приемов. Но это касается в большей степени рефакторинга. Поэтому в данной статье не описываются.

Да, еще про печать. Тема от ineoosaki. Вот несколько приемов. При выводе печатных форм опимизировать можно код и таблицу.

Девятый прием. Выражения выводимые при печати лучше рассчитывать в модуле, а не в таблице использующейся в качестве шаблона. Данная рекомендация есть на диске ИТС.

Десятый прием. Шаблон печатной формы. Чем меньше ячеек содержит результирующая таблица, тем меньше памяти потребуется для ее отображения, тем быстрее будет выполняться навигация по таблице.

Одиннадцатый прием. Для больших таблиц также применим метод определения эффективной порции. Т.е. большой отчет может быть разбит на несколько небольших отчетов. Это тоже позволит поднять производительность печати.

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

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


Оценка сообщества

Плюсы (+30):

, , , , , , , , , , , , , , , , , , , , , , , , , , , , ,


Добавить плюс Добавить минус

Комментарии (50)

Страницы: 123 Вперед

1.
+ -
31.01.2009 23:01:37

хорошая статья для новичков. +1
Я бы добавил, еще, что при разработке отчетов/печатных форм надо стараться вычислять выражения в модулях, а не в таблицах.

2.
+ -
01.02.2009 00:02:11

плюс выигрыш при заполнении областей в печатных вормах

3.
+ -
01.02.2009 01:02:03

А вот если Ускоренное создание объектов в 1С: http://www.1cpp.ru/forum/YaBB.pl?num=1215146216 в функционал turbobl.dll добавить, стало бы еще лучше.

4.
+ -
01.02.2009 02:02:21

(3) Зачем? Функционал turbobl.dll полностью присутствует в 1CPP.dll. http://www.1cpp.ru/index.php/VeryBeginning

5.
+ -
01.02.2009 02:02:17

Тут есть некоторая подстава: 1++ конечно содержит весь функционал ускорения, но накладные расходы на дополнительные возможности 1с++ (не все можно отключить) съедают все ускорение. Если мы хотим ускорить штатные функции с минимальным изменением кода turbobl.dll все оказывается значительно лучше 1с++

6.
+ -
01.02.2009 02:02:55

Кстати, вот еще одно ускорение "Быстрые и медленные переменные" http://subscribe.ru/archive/comp.soft.prog.school1c/200501/18080241.html сам не проверял ;)

7.
+ -
01.02.2009 08:02:08

Функция, заменяющая стандартные методы СоздатьОбъект("ТаблицаЗначений") и СоздатьОбъект("СписокЗначений"), подсмотренная в конфе СКАТ-профессионал, от 33lab:

Функция _Новый(стрОбъект) Экспорт
Если стрОбъект = "СписокЗначений" Тогда
Возврат ЗначениеИзСтрокиВнутр("{""VL"",{}}");
КонецЕсли;
Если стрОбъект = "ТаблицаЗначений" Тогда
Возврат ЗначениеИзСтрокиВнутр("{""VT"",""1"",{""0"",{{"""",""0"",""0"",""0"","""",""2""}}}}");
КонецЕсли;

КонецФункции

8.
+ -
01.02.2009 11:02:29

(5) C чего ты это взял-то про "накладные расходы на доп.возможности 1С++) съедают все ускорение" ? :(
Последние версии 1С++ 3.0.1.ХХ еще сильнее ускоряют 1С даже по сравнению с ТурбоБЛ :)

(7) Кстати, в последних версиях 1С+ 3.0.1.ХХ списки и таблицы значений автоматически создаются намного быстрее, чем в простой 1С, и даже чуть быстрее указанного тобой известного способа :)

9.
+ -
01.02.2009 12:02:14

По поводу печатных форм - еще ускорит формирование применение ранее подготовленных секций.

10.
+ -
01.02.2009 13:02:31

(8) В 1С вообще тесты скорости радуют своей неповторяемостью, поэтому скорость я замерял в ТиС-Демо вот таким образом: обработка перепроводила документы, документы перепроводились несколько раз, либо цепочка документов несколько раз проводилась, в лог попадали min/max/avg.
У меня на этом тесте получилось что максимальная скорость достигается именно с ТурбоБЛ. Если отключить перехватчики в 1C++ скорость повышается, но все равно медленнее чем с ТурбоБЛ.
Проверял я это после введения ускоренного создания объектов в 1С++, честно говоря, был удивлен полученным результатом.

11.
+ -
02.02.2009 00:02:47

Последнее предложение в 10-м приёме (Объединяем ячейки таблицы.) в корне не верно! Чем больше объединённых ячеек, тем медленнее становится таблица. Старайтесь вообще избегать объединений, лучше воспользоваться "по выделенным столбцам"

Ну и про переменные, которые надо сделать глобальными в текущем модуле. Уж не знаю на сколько ты при этом выиграешь в скорости, но вот неожиданных засад ты получаешь тем больше, чем больше у тебя таких переменных.

12.
+ -
02.02.2009 00:02:47

Автор, ты про главный инструмент забыл - ОТЛАДЧИК с замером ;)

[+]:
13.
+ -
02.02.2009 06:02:29

(11) Отчет на котором я "тренировался" в первоначальном варианте без объединения "съедал" 700 Mb оперативной памяти, а на чем "тренировались" вы?

(12) Ну, это очевидное. Не хотелось бы переписывать документацию...

14.
+ -
02.02.2009 07:02:53

(11) Ага, про глобальные переменные это очень верно :)
(13) Отладчик с замером обязательно нужно упомянуть - без него никуда!

(10) Давай на сайте 1С++ обсудим эту тему?

15.
+ -
02.02.2009 10:02:13

10 предложение - гон чистой воды...
Объединенные ячейки - смерть для мокселя... равно как и любые внедренные объекты - картинки, оле-объекты...

16.
+ -
02.02.2009 10:02:01

Собственно автором вопроса про производительность/методы был я.
Спасибо за статью, будет полезна новичкам: недавно натолкнулся на http://infostart.ru/projects/3334/ - после просмотра кода пришел в ужас.

Вопросы вызывают пункты 7 и 11 (как и у всех).

Повсеместное использование глобальных переменных до добра не доводит. Должен быть баланс: иногда логичнее применить способ оптимизации 1 (железа или вообще технология).

Собственно к камням :)
Документ ВводРасчетов модуль документа:

Процедура ОбработкаПроведения(Режим = 0)
// Режим = 0 - провести документ без формирования движений по документу
// Режим = 1 - удалить движения документа
// Режим > 1 - допроведение документа

Если ГрупповаяОбработка() = 1 Тогда
глСообщениеГрупповойОбработки(ТекущийДокумент);
СтатусВозврата(0); Возврат;
ИначеЕсли Режим = 0 Тогда
Возврат;
КонецЕсли;

Если ДатаДок <> НТП Тогда
Предупреждение("Этот документ можно провести только в текущем периоде!");
СтатусВозврата(0); Возврат;
КонецЕсли;

Для Сч = 1 По _гл_СписокАбонентов.РазмерСписка() Цикл
Аб = _гл_СписокАбонентов.ПолучитьЗначение(Сч);
ИнициализацияАбонента();
КонецЦикла;

КонецПроцедуры //ОбработкаПроведения

При интерактивном проведении _гл_СписокАбонентов заполняется. А что будет если мне забожается выполнить ДокВводРасчетов.Провести() из кода обработки?

МНЕ кажется такой подход не оправдан. Не стоит раскидывать логику проведения по разным местам.


17.
+ -
02.02.2009 10:02:53

(16) Я думаю что применение любого из предложенных приемов каждый определяет для себя сам. В конфигурациях фирмы 1С часто создается таблица товаров, а затем передается и модифицируется всеми процедурами модуля объекта. Речь собственно шла именно о таких случаях.

По 11 приему вроде не было вопросов. Скоро сделаю обезличенную базу - посмотреть как это выглядит можно будет там.
По 10 приему - можно еще погонять тесты, но варианта без объединения по вертикальным секциям состоящих из нескольких строк я не представляю...

> При интерактивном проведении _гл_СписокАбонентов заполняется. А что будет если мне забожается выполнить ДокВводРасчетов.Провести() из кода обработки?
Внутри конфигурации есть групповая обработка документов. Там все работает как надо...
Сейчас проверю. Добавлю статистику по этому вопросу...

18.
+ -
02.02.2009 11:02:45

(17) конечно же имел ввиду 10 пункт.

Я НЕ сомневаюсь, что работает как надо :).

Речь об "изолированности" что-ли. Ведь можно передавать список в качестве параметра для функции проведения: ОбработкаПроведения(вхСписокАбонентов), и получить более "устойчивый" функционал :)

З.Ы. Сейчас задам вопрос в теме http://infostart.ru/projects/3163

19.
+ -
02.02.2009 12:02:34

(18) По пятому приему статистика следующая:
При проведении документа в 1 транзакции время проведения не стабильно в течении сеанса:
1 проведение - 128 секунд
2 проведение - 216 секунд
3 проведение - 235 секунд
4 проведение - 700 секунд
5 проведение - 221 секунда
6 проведение - 668 секунд

При использовании приема время проведения стабильно в течении сеанса - 49 секунд

20.
+ -
02.02.2009 16:02:48

+19
В 19 посте данные при работе в монопольном режиме.
В разделенном режиме терминальной сессии картинка иная.

Проведение в 1 транзакции
1 проведение - 756 секунд
2 проведение - 955 секунд
3 проведение - 1080 секунд
4 проведение - 1056 секунд

Проведение с использованием 5 приема - 65 секунд стабильно

Страницы: 123 Вперед

51.

* При ответе на комментарий, указывайте его номер в круглых скобках, например, (1).

Есть вопросы?
тел. (812) 309-06-46
support@infostart.ru
Обратная связь
slavamts
Слава

Новейший отчет 7.7: ПРОФ Антикризис за 4850 руб.

Не успели перейти на восьмерку? Новейший отчет - это полный управленческий анализ в семерке (1С 7.7). Все данные у вас есть в базе, надо только наглядно их показать!

Кто накосячил в базе 1С?

История изменений ДО РЕКВИЗИТА! ВОССТАНОВЛЕНИЕ объекта на дату! Быстрый поиск по журналу изменений. История по текущему объекту одним кликом.

Комплекс защиты конфигураций 2.0.

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

Печатные формы (21 шт.).

Пакетная (групповая) печать исходящих накладных, а так же входящих! Экономит время и нервы.

Анализ взаиморасчётов (акт сверки) для 1С 8.0 (БП, УПП)

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

Объявления с картинками — бесплатные показы, оплата за клики. Разместить свое объявление