Многопоточность как способ ускорения некоторых процедур

Платформа 1С:Предприятие 8 обладает необходимыми инструментами для обеспечения многопоточности, но на практике про эти инструменты незаслуженно забывают.

Конечно, многопоточность – это не панацея, но это хороший способ для:

1)      уменьшения длительности выполнения длительных процедур (в некоторых ситуациях — на порядки!);

2)      повышения утилизации ресурсов оборудования.

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

Пара примеров:

1)      Существует несколько сотен магазинов, работающих на самописном ПО, и единая база в головной компании, куда ежедневно выгружаются транзакции по продажам. Загрузка инициируется пользователем по кнопке и занимает длительное время, т.к. магазинов много и транзакций приличное количество, а обработка пакетов данных идет последовательно.

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

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

2)      Существует большая база данных с транзакциями по продажам магазинов (из предыдущего примере) и есть необходимость периодически выгружать эти данные в стороннюю BI-систему средствами 1С. Выгрузка инициируется пользователем и занимает длительное время, т.к. системе нужно получить из базы данных миллионы строк и выгрузить их в промежуточную базу для BI. Во время выгрузки данных оборудование загружено несущественно.

В этой ситуации можно было бы распараллелить выгрузку данных – одновременно выгружать данные по разным магазинам. Это существенно ускорит процесс и позволит в полной мере ощутить эффект от мощного железа.

Инструменты встроенного языка для выполнения многопоточной процедуры.

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

Пример кода для второго случая (выгрузка большого массива данных порциями):

1)      Процедура, инициирующая многопоточное выполнение кода:

 Процедура КнопкаВыполнитьНажатие(Кнопка)

    //указывает число потоков, которые будут запущены одновременно
   
ЧислоПараллельныхПотоков = 10;

    МассивЗаданий = Новый Массив;

    Запрос = Новый Запрос(
   
«ВЫБРАТЬ РАЗЛИЧНЫЕ
    |    ПартииТоваровНаСкладах.Склад
    |ИЗ
    |    РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
    |ГДЕ
    |    ПартииТоваровНаСкладах.Период МЕЖДУ &Дата1 И &Дата2″
);
   
Запрос.УстановитьПараметр(«Дата1», ДатаНачала);
   
Запрос.УстановитьПараметр(«Дата2», ДатаОкончания);

    Результат = Запрос.Выполнить().Выгрузить();

    Для каждого Стр из Результат Цикл

        МассивПараметров = Новый Массив;
       
МассивПараметров.Добавить(ДатаНачала);
       
МассивПараметров.Добавить(ДатаОкончания);
       
МассивПараметров.Добавить(Стр.Склад);

        Задание = ФоновыеЗадания.Выполнить(«ВыгрузкаДанныхНаСервере.ВыгрузитьДанныеПоПартиям», МассивПараметров);

        МассивЗаданий.Добавить(Задание);

        Если МассивЗаданий.Количество() >= ЧислоПараллельныхПотоков Тогда
            Попытка
               
ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
            Исключение
            КонецПопытки;
           
МассивЗаданий.Очистить();
        КонецЕсли;

    КонецЦикла;

    Если МассивЗаданий.Количество() > 0 Тогда
        Попытка
           
ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
        Исключение
        КонецПопытки;
       
МассивЗаданий.Очистить();
    КонецЕсли;

    Сообщить(«Время выполнения процедуры — » + (ТекущаяДата() — ВремяНачала) + » с.»);

КонецПроцедуры

2)      Процедура, которую непосредственно выполняет фоновое задание (основная логика):

 Общий модуль «ВыгрузкаДанныхНаСервере», выполняемый на сервере:

Процедура ВыгрузитьДанныеПоПартиям(ДатаНачала, ДатаОкончания, Склад) Экспорт

    Запрос = Новый Запрос(
   
«ВЫБРАТЬ
    |    *
    |ИЗ
    |    РегистрНакопления.ПартииТоваровНаСкладах КАК ПартииТоваровНаСкладах
    |ГДЕ
    |    ПартииТоваровНаСкладах.Период МЕЖДУ &Дата1 И &Дата2
    |    И ПартииТоваровНаСкладах.Склад = &Склад»
);

    Запрос.УстановитьПараметр(«Дата1», ДатаНачала);
   
Запрос.УстановитьПараметр(«Дата2», ДатаОкончания);
   
Запрос.УстановитьПараметр(«Склад», Склад);

    Результат = Запрос.Выполнить().Выгрузить();

    Для каждого Стр из Результат Цикл
       
//Что-то делаем с данными
   
КонецЦикла;

КонецПроцедуры

 При этом случает учесть, что к выбору числа параллельных заданий нужно отнестись ответственно – если запустить их даже несколько десятков, то велика вероятность «повесить» и сервер приложений, и сервер СУБД.


75 Comments

  1. stanru1

    А где гарантии, что несколько фоновых задании распараллелятся по нескольким ядрам? Тут, видимо, надо подумать и на тему создания рабочих процессов (т.к. фоновые задания запускаются в своих сеансах)?

    Reply
  2. Aleksey.Bochkov

    (1) — фоновые задания однозначно параллелятся на разные ядра. Сервер 1С — это многопоточное приложение, которое способно задействовать все ядра даже при одном рабочем процессе.

    Reply
  3. stanru1

    (2) не поленился проверить. да, вы правы — загружает все доступные ядра при росте нагрузки.

    Reply
  4. yuraos

    В целом плюс за оригинальную идею



    но все-таки это «фоновые задания«,

    а не «многопоточность выполнения» в том смысле,

    котором она трактуется в курсах по теории операционных систем.



    более коррекно было бы говорить о использовании

    фоновых заданий для выполнения параллельной обработки данных.

    Reply
  5. redwonder87

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

    Reply
  6. soba

    В файловом варианте, надо полагать, точно так же реагирует ? Или применимо только к Клиент-серверному варианту?

    Для меня актуально для формирования и рассылки отчетов клиентам по итогам периода, а проверить-то и некогда в ближайшие дни

    Reply
  7. Serj1C

    (6) в файловой с фоновыми заданиями облом

    Reply
  8. Aleksey.Bochkov

    (4) — если смотреть определение «многопоточности» в википедии, то вы правы — это более сложное понятие и не совсем тут применимо, но мне показалось, что этот термин допустим, т.к «многозадачность», более подходящая тут по смыслу, для большинства будет не так очевидна. Опять же — сугубо ИМХО.

    Reply
  9. Timur_Bagautdinov

    (0) А какие-нибудь замеры производительности делались? Какова величина ускорения и эффективности?

    Имеет ли смысл этим заниматься, если прирост не столь существенен

    Reply
  10. СергейКа

    В целом мы давненько это используем, но тут есть пара условий:

    1) конфигурация должна быть самописная или переписанная типовая, без изменения самой конфигурации не сделаешь;

    2) клиент-серверный вариант;

    3) с фоновыми иногда проблемы в платформе бывают, так что нужен дополнительный контроль.

    Reply
  11. Aleksey.Bochkov

    (9) — в этом уравнении много переменных, поэтому конкретные замеры приводить бесполезно.

    Все зависит от:

    1) характера операции, которую «параллелят»

    2) доли параллельных операций в общем объеме (как в моем первом примере, когда только часть процедуры выполняется параллельно)

    3) мощности железа — грубо говоря, однопроцессорный сервер «потянет» 10 одновременных фоновых заданий, а четырехпроцессорный — 50-100. Замеры будут совсем разные.

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

    Reply
  12. Timur_Bagautdinov

    (11) Как это бесполезно замерять?

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

    1. Узнать, какое ускорение принес метод параллельной обработки данных. На повышение производительности влияет много факторов. Ведь получив прирост 5-10%, дополнительный повод для подробного исследования алгоритма.

    2. Также следует знать эффективность. Параллельный алгоритм может давать большое ускорение, но использовать для этого множество процессов неэффективно. Грубо говоря добавили 100 процессоров, а ускорение вышло всего в 2 раза.

    3. Понимать насколько масштабируемо решение. Например, 4 фоновых процесса работают на ура, а 8 уже нет, к примеру, не хватает уже оперативной памяти.

    Итого, замер — обратная связь от наших действий.

    Вот у Вас приведено две конкретных задачи. Интересно узнать, как в вашем случае такой подход дает выхлоп.

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

    В любой распространенной библиотеке для высокопроизводительных вычислений MPI, OpenMP, TBB и т.п. есть демо примеры, есть опыт сообщества — везде рисуют графики, приводят замеры, делятся опытом.

    Reply
  13. comol

    «бородатый баян» конечно, но людям, пожалуй, полезный…

    Reply
  14. comol

    (2) Не совсем верно конечно… нити по ядрам распараллеливает Windows, а не сервер 1С. Сервер 1С их только создаёт. Самое главное что сервер 1С создаёт поток только для сеанса (или для соединения), следовательно если у вас будет одно соединение, которое будет выполнять всю «тяжелую работу» все ядра сервер 1С не загрузит. До многопоточности, которая существует в нормальных серверах СУБД, серверу 1С конечно ещё далеко…

    Reply
  15. frc

    (8)

    Наиболее эффективно организовать многопоточность можно с помощью Фоновых заданий (не путать с регламентными заданиями).

    Фоновые и регламентные — одно и то же:

    одни запускает сервер, вторые — тоже сервер, но по отмашке пользователя.

    Но все выполняются в порядке очереди с основным расчетом.

    Где тут автор увидел многопоточность — непонятно…

    Reply
  16. frc
    При этом случает учесть, что к выбору числа параллельных заданий нужно отнестись ответственно – если запустить их даже несколько десятков, то велика вероятность «повесить» и сервер приложений, и сервер СУБД.

    Авторо, покурите на досуге собственную фразу — почему нельзя, и где тут многопоточность вдруг нашлась.

    Reply
  17. Aleksey.Bochkov

    (12) — не нужно искажать фразы :).

    Я писал про бесполезность приведения (публикации) результатов, а не бесполезность самих замеров.

    Ну сделаю я замеры на своем железе и получу прирост в 100 раз, а вы повторите у себя и получите 80-кратный прирост — результат получается не чистым.

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

    Я лишь привел инструмент. Детальный анализ его эффективности — это уже задача разработчика в конкретной ситуации. Хотя могу и я сделать, не за бесплатно, конечно :).

    Reply
  18. Aleksey.Bochkov

    (13) — насчет баяна не согласен 🙂

    Вроде все знают о фоновых заданиях, а о том, что их так можно использовать — не все догадываются.

    (14) — в моей формулировке «Сервер 1С — это многопоточное приложение, которое способно задействовать все ядра даже при одном рабочем процессе.» нет уточнения входных параметров, поэтому в общем случае она верна. Тем более, что это почти дословно слова Сергея Нуралиева. Ему, как разработчику, виднее.

    Reply
  19. Aleksey.Bochkov

    (15) — советую почитать желтые книжки. Фоновые и регламентные задания — это разные вещи.

    Если простыми словами:

    Фоновое задание — выполнение кода в отдельной сессии.

    Регламентное задание — комбинация расписания и фонового задания.

    Reply
  20. Aleksey.Bochkov

    (16) — на досуге советую потренировать восприятие чужих текстов и постараться меньше хамить без приведения здравой критики :).

    Предупреждение «При этом случает учесть, что к выбору числа параллельных заданий нужно отнестись ответственно – если запустить их даже несколько десятков, то велика вероятность «повесить» и сервер приложений, и сервер СУБД.» достаточно простое, понятное и в тему.

    Reply
  21. stanru1

    (14) жаль, я вчера не заскриншотил, 1с (или Windows) чудесно загрузила все 32 ядра при увеличении количества фоновых заданий.

    (12) Timur_Bagautdinov, не поленился, вот результаты теста:

    от 1 до 10 одновременно запущенных фоновых заданий.

    каждое задание 10 млн раз занималось делением случайных чисел

    среднее время выполнения каждого задания в мс

    Reply
  22. comol

    (17) frc, давайте погрузимся дальше — тоже не верно. число одновременно выполняемых операций процессором определяется числом возможных очередей команд. Команды в очередь помещает даже не процесс и не системное ПО, что-то распарралеливает только сам процессор. так? А если ещё глубже могёте? :))))

    Reply
  23. comol

    (19) Фраза то верна, но такое определение очень часто вызывает недопонимание «почему у меня при расчете себестоимости только одно ядро загружено, где ваше многопоточное приложение?»…

    Reply
  24. w-divin

    (22) Правильнее было бы показывать не среднее время каждого задания, а общее время выполнения всех заданий в вариациях очередь по 1, очередь по 2, очередь по 3… все 10 одновременно

    Reply
  25. Timur_Bagautdinov

    (18) А что, у «1С» по этому поводу публикации есть? Можно ссылочки на них?

    Не хотите давать результатов, что ж, Ваша статья голословна.

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

    То что платформа «1С» не предоставляет таких инструментов, не значит, что в многопоточном режиме решаются задачи только с независимым разбиением на нити по данным.

    (22) А что должен показать данный график? В чем его смысл?

    Reply
  26. frc

    (23) comol,

    совершенно неверно путать очередность выполнения команд процессора, распараллеливание процессов в ОС и параллельные вычисления.

    Первое — делает процессор ко всем без исключения командам, поступающим к нему — будь то запись файла или какой-то расчет в 1С. Предугадал команду, совпало — «распараллелил», нет — по очереди.

    Второе — делает ОС по отношению к своим процессам: может икнуть какой-то процексс на другое ядро там и т.д. — кидает. Нет (по разным своим системным причинам — и отнюдь не зависящим от параллельности процессов) — идут на выполнение друг за другом.

    А третье — третье не реализовано в 1С.

    (20)

    Фоновое задание — выполнение кода в отдельной сессии.

    Регламентное задание — комбинация расписания и фонового задания.

    т.е. расписание — это превращает фоновое задание в «нечто другое»? 🙂

    Reply
  27. stanru1

    (25) w-divin, вот время выполнения «пакетов» фоновых заданий

    (26) Timur_Bagautdinov,

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

    Reply
  28. verter.me

    Отличная статья Алексей.

    Reply
  29. smilejka

    (28) stanru1,

    Непонятно по графику:

    получается чем больше потоков, тем больше время выполнения операции? Тогда это никакое не ускорение процедур…

    Reply
  30. yuraos

    (20)

    это как раз тот случай,

    когда в «желтых» книжках

    (как и в библии или в полном собрании сочинений ВИЛ-а)

    действительно можно вычитать что-нибудь полезное.

    Reply
  31. yuraos

    (27) frc,

    я бы сказал так:

    регламентное задание —

    это «расписание» запускающее фоновые задания, выполняющие код

    (фоновых заданий может быть к стати много).

    не расписание «делает» фоновое задание регламентным,

    но фактически расписание и само есть регламентное задание.

    Reply
  32. yuraos

    (7) Serj1C,

    я бы сказал не облом … а хуже — «ГЕММОРОЙ«.

    В принципе можно запускать фоновые задания в специально

    отведенном для этого соединении с файловой базой.

    Только машинка должна быть помощьней и сетка пошустрей,

    чтобы добиться того, что здесь обсуждается.

    Reply
  33. stanru1

    (31) smilejka, график как раз показывает, что одновременно выполняемые 10 заданий будут выполнятся (все! общее время выполнения) лишь в полтора раза дольше, чем 1.

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

    С исключениями, о которых писал в публикации автор.

    Reply
  34. Fragster

    У меня есть многопоточный тест производительности: http://infostart.ru/public/173394/

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

    Reply
  35. OrsoBear

    Да, тоже недавно начал пользоваться этим методом.

    Настало время, когда параллельно несколькими делами надо заниматься.

    Reply
  36. Yashazz

    Для меня это баян старинный. К тому же, и на ИС подобное уже вроде было. Напрашивающееся же решение…

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

    Если я правильно понял в своё время Гилёва, то сервер 1С ничего не распараллеливает по ядрам, и будь хоть стоядерный процессор, важна его частота, а не количество ядер, потому что 1С их не задействует оптимально.

    Reply
  37. KroVladS

    (0)

    Очень интересный механизм.

    У меня как раз есть задача для его применения. Надо будет обязательно попробовать.

    Спасибо за статью.

    Reply
  38. stanru1

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

    рабочий процесс один. Изначально загружены 1-2 ядра. Начинаем запускать фоновые задания. Под конец эксперимента загрузились все ядра.

    Reply
  39. _HakerAlex_

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

    Reply
  40. Fragster

    (41) AlexPotemkin123, ну, например, долгие расчеты, восстановление последовательности и прочее — вполне себе параллелится. Проведение одного документа параллелить, конечно, смысла мало.

    Reply
  41. KroVladS

    Проверил на реальной задаче.

    Есть надстройка над УТ 10.3 для работы с КПК «Агент+».

    Типовая задача выгрузка данных всем Агентам.

    Я ограничил выгрузку первыми 10 агентами, вот результат:

    Обычная выгрузка. БЕЗ фонового задания.

    Общая выгрузка. Время выгрузки 262 с

    Фоновое задание 1 поток.

    Общая выгрузка. Время выгрузки 223 с

    Фоновое задание 2 потока.

    Общая выгрузка. Время выгрузки 157 с

    Фоновое задание 5 потоков.

    Общая выгрузка. Время выгрузки 73 с

    Фоновое задание 10 потоков.

    Завершаеться с ошибкой, но создались файлы для 7 агентов:

    Ошибка при вызове метода контекста (ОжидатьЗавершения): Выполнение одного или нескольких заданий завершилось с ошибкой

    на строке:

    ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);

    Я думаю и без красивых графиков преимущества очевидны.

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

    Reply
  42. Fragster

    (43) KroVladS, интересно, с чем связано то, что 1 фоновое задание выполняется быстрее, чем просто в предприятии?

    Reply
  43. Гость

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

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

    То что сервер 1С не может создать дополнительный поток для одного клиента как раз приводит к тому что многопоточность нельзя реализовать в 1С стандартными для других языков программирования средствами. Нет класса Thread. Это ограничение продиктовано скорее прикладным назначением клиентских подключений, нежели непродуманностью платформы и желанием ее разработчиков облегчить себе жизнь 🙂

    Но способность самого сервера 1С создавать потоки для фоновых заданий и запускать их параллельно от выполнения «клиентского» кода от этого никуда не исчезает.

    Reply
  44. KroVladS

    (43) KroVladS,

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

    Домыслы:

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

    2. При выполнении на клиенте выводиться лог работы выгрузки, примерно так:

    #Если Клиент Тогда
    Состояние(«Выполенение операции №1…»);
    СтартОперации=ТекущаяДата();
    #КонецЕсли
    
    ВыполнитьОперацию1();
    
    #Если Клиент Тогда
    СтопОперации = ТекущаяДата();
    Сообщить(«Выполенение операции №1 =»+(СтопОперации — СтартОперации));
    #КонецЕсли

    Показать

    по 20 раз для каждого агента.

    на сервере они соответственно не выполняются,

    3. Запуск фонового задания происходит из Привилегированного модуля, может не происходит проверка на права и РЛСы.

    Reply
  45. KroVladS

    Сделал график к данным из (43).

    Reply
  46. nicxxx

    присоединяюсь к (15). в файловом варианте распараллеливания не происходит, все задания из массива выполняются последовательно.

    Reply
  47. stanru1

    (48) использовать файловый вариант и фоновые задания на мой взгляд в принципе извращение. только если по-иному уж совсем никак нельзя.

    Reply
  48. nicxxx

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

    Reply
  49. KroVladS

    Добавил проверку на выполнение фонового задания, если задание завершилось неудачно перезапускаю 5 раз.

    Добавил в рабочую базу, 60 заданий в 60 потоков, из них 4-5 заданий перезапускаются из-за блокировок.

    Итог ПОЛТОРЫ минуты вместо получаса.

    Может для кого то это и «бородатый баян», но мне эта публикация очень помогла.

    Спасибо.

    Reply
  50. Fragster

    (51) KroVladS, Количество фоновых можно подобрать тестом из (36). обычно больше 8-16 смысла не имеет, а наибольший прирост — так вообще на 4-8

    Reply
  51. KroVladS

    (52) Fragster,

    Экспериментировал с разным количеством потоков.

    Проблема в том, что не все задания равнозначны, разброс по времени от 20 сек. до 60 сек. Блокировки начинаются примерно от 10 потоков, причём проблемы именно с долгими заданиями.

    Можно запустить в 8 потоков, но это в три раза дольше, при этом нет гарантии что оно всегда будет выполняться без блокировок.

    Я решил сделать каждое задание в свой поток, но отслеживать и перезапускать отвалившиеся задания.

    Reply
  52. Fragster

    (53) KroVladS, нужно сделать диспетчер очередей и как только одно заканчивается — запускать новое. я одно время пытался заморочится внешним (из-за того, что у 1с нету функции паузы, которая бы не грузила процессор), чтобы не перезапускать задания (которые сами по себе несколько секунд могут запускаться), а вместо этого сделать постоянный «пул заданий», которому бы просто «независимые атомы» из очереди можно было бы запихивать, но не взлетело, к сожалению.

    Reply
  53. yuraos

    (54) Fragster,


    …(из-за того, что у 1с нету функции паузы, которая бы не грузила процессор)…

    тут есть народное средство от StepByStep

    для имитации паузы в 1С:

    // Функция задержки выполнения процесса.
    //
    &НаКлиентеНаСервереБезКонтекста
    Процедура ЗадержкаВВыполнении(ВремяОжидания)
    Попытка
    xPing = «ping -n 1 -w «+Формат(1000*ВремяОжидания, «ЧГ=0″)+» 127.255.255.255″;
    WshShell = Новый COMОбъект(«WScript.Shell»);
    WshShell.Run(xPing, 0, -1);
    Исключение
    КонецПопытки;
    КонецПроцедуры
    

    Показать

    его не пробывал ???

    (конечно если сервер под виндой )

    Reply
  54. Fragster

    (55) yuraos, про этот способ я знаю, сам его использую, причем несколько более кроссплатформенным образом (опять же в (36), работает начиная с 8.2.14):

    Процедура Пауза() Экспорт
    Инфо = Новый СистемнаяИнформация();
    Если
    Инфо.ТипПлатформы = ТипПлатформы.Windows_x86 ИЛИ
    Инфо.ТипПлатформы = ТипПлатформы.Windows_x86_64
    Тогда
    ЗапуститьПриложение(«ping -n 2 127.0.0.1», , Истина); // windows
    Иначе
    ЗапуститьПриложение(«ping -c 2 127.0.0.1», , Истина); // linux
    КонецЕсли;
    КонецПроцедуры
    

    Показать

    однако для очередей, о которых я говорю 1 секунда — слишком много, вот если бы 1/50 секунды, тогда да, имело бы смысл не выключать фоновые задания, но такое только с помощью ВК или другого внешнего приспособления может быть достигнуто (причем менее стандартного, чем пинг).

    Reply
  55. Artemuch2

    Да идея ничего так. Надо будет попробовать

    Reply
  56. AlexBar

    Я использую данную технологию уже более 2-х лет. Ранее я уже несколько раз писал об этом на ИС. Автор молодец, что оформил саму технологию в виде публикации.

    Я считаю что споры о том что есть фоновое задание, что есть регламентное задание абсолютно не уместны. Так же как и придирки к понятию «многопоточности». Для того, чтобы построить многопоточность, нужно вообще понять как распараллелить сам код и контекст его выполнения. Все фоновые задания, не важно чем они запускаются (командой пользователя или регламентным заданием), выполняются в параллельном режиме (клиент-серверный режим), а это значит что любая операция, которую можно разложить на несколько параллельных независимых операций, выполнится на порядки быстрее, пусть не в N количества операций, но быстрее в разы однозначно.

    Количество параллельных заданий так же является спорным параметром, так как все зависит от того, как сильно код, исполняемый заданием, грузит процессор(ы). Если в задании производить мелкие математические операции, то можно запустить и 1000 заданий параллельно, процессор ничего не «почувствует». Если в задании производить чтение/запись данных, выполнение запросов к ИБ, то нагрузка будет увеличиваться по вполне понятным причинам.

    Я не ограничиваюсь каким-либо числом заданий, а использую функцию, которая определяет общую загрузку процессоров сервера. Это дает мне возможность определить не только работоспособность n-числа фоновых заданий, но и комфортность работы пользователей. т.е. создаваемые фоновые задания не должны тормозить работу пользователей, создавая избыточную загрузку ресурсов сервера. Мои методы создают такое количество заданий, пока загрузка процессоров не достигнет 70%. Сколько при этом создастся фоновых заданий — совершенно не важно. Возможно что код такой тяжелый, что и одно задание загрузит сервер под завязку, тогда и никакое «распараллеливание» не поможет, так как 2 подобных задания параллельно будут выполнятся столько же времени сколько и последовательно, если не дольше.

    Для контроля выполнения заданий дополнительно использую регистр сведений. К примеру требуется разузловать 100 строк таблицы Продукция. Вполне понятно что эту процедуру можно производить параллельно, вот только результаты нужно сложить. Запускаю в цикле фоновые задания и создаю записи в РС. Там, где задание отработало, оно устанавливает признак в своей строке РС и записывает туда результат. Когда все задания отработают, собираем из РС результат. Не претендую на исключительность, можно реализовать и иначе, просто делюсь опытом.

    Reply
  57. relanium86

    Странно у меня получилось следущиее

    Время выполнения процедуры — 102 с. с фонововыми

    Время выполнения процедуры — 7 с. без фоновых

    Ниже код

        //указывает число потоков, которые будут запущены одновременно
    //ЧислоПараллельныхПотоков = 10;
    
    //МассивЗаданий = Новый Массив;
    ВремяНачала = ТекущаяДата();
    
    Для а = 1 По 50 Цикл
    ГСЧ = Новый ГенераторСлучайныхЧисел;
    Параметр = а*ГСЧ.СлучайноеЧисло(0, 10000);
    //МассивПараметров = Новый Массив;
    //МассивПараметров.Добавить(100000);
    //МассивПараметров.Добавить(Параметр);
    СерверныйМодуль.РасчитатьЧисло(100000, Параметр);
    //Задание = ФоновыеЗадания.Выполнить(«СерверныйМодуль.РасчитатьЧисло», МассивПараметров);
    
    //МассивЗаданий.Добавить(Задание);
    
    //Если МассивЗаданий.Количество() >= ЧислоПараллельныхПотоков Тогда
    // Попытка
    //  ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
    // Исключение
    // КонецПопытки;
    // МассивЗаданий.Очистить();
    //КонецЕсли;
    
    КонецЦикла;
    
    //Если МассивЗаданий.Количество() > 0 Тогда
    // Попытка
    //  ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
    // Исключение
    // КонецПопытки;
    // МассивЗаданий.Очистить();
    //КонецЕсли;
    
    Сообщить(«Время выполнения процедуры — » + (ТекущаяДата() — ВремяНачала) + » с.»);
    

    Показать

    Почему так интересно?

    Reply
  58. yuraos

    (59) relanium86,

    распараллеливание — не панацея,

    это дело как Восток — тонкое.

    не все задачи можно распараллелить вообще

    и оптимально распарралелить в частности.

    Reply
  59. Fragster

    (59) relanium86, сами по себе фоновые задания запускаются ощутимое время, по этому для операций < десятков секунд смысла вообще нет (или нужны постоянно запущенные задания «в боевой готовности»)

    Reply
  60. DitriX

    Да тут вообще по ходу никто толком не решал проблему с распаралеливанием, иначе столкнулись бы с тем же, с чем столкнулись в (58).

    Распаралелить в 1С вообще по сути ничего нельзя, по крайней мере до УТ11 и технологии РАУЗ, та и то с ней — спорно все очень.

    А видь проблемы то 2:

    1. Как собрать, то что получилось;

    2. Как не убить сервер нагрузкой.

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

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

    И запускается регламент, каждую 1 минуту (это я вывел экспериентальным путем), регламент обращается к регистру и смотрит — есть ли строка выгрузки без флага начала загрузки, если есть — он ставит флаг и идет работать, если все занято — просто отдыхает.

    Таким образом, я делаю контроль выгрузки, туда же попадают ошибки и т.д. и т.п.

    Кроме этого — я еще сделал «Вес выгрузки», т.е. я знаю что на 4 склада идет ооочень большая выгрузка, я им сделал вес выше, и при запуске регламента — программа смотрит, если вес больше 20 (крупный склад — Вес = 10, мелкие — от 1 до 5), то он не делает выгрузку.

    Таким образом — я не делаю на сервер мгновенную нагрузку, т.е. когда запускается сходу 10 потоков, и все начинают плакать, и не нагружаю сервер.

    Но это все костыли, а не многопоточность или мультизадачность 🙂

    (58) а как вы отлавливаете нагрузку на проц? Я тоже думал, но столкнулся с ньюансами, иногда — проц просто на секунд 20 — 30 загружался под 90%, когда были какие то загрузки/выгрузки, и если я попадал на этот промежуток, то я не запускал задания, в итоге — идея оказалось провальной, так как бегая за поддержанием производительности — я тратил в 10 раз больше времени, чем если бы запустил все в одном потоке.

    И когда идет вызов фонового задания

    Reply
  61. AlexBar

    (62)Многопоточность, многозадачность… не суть важно. Вариант ускорения выполнения какого-либо кода все равно имеется в клиент-серверной архитектуре, так что будем пользоваться. Любые рассуждения на тему того, что задания выполняются не совсем параллельно естественно верны, так как сами задания запускаются поочередно в цикле, следовательно если считать время запуска и время выполнения каждого задания равным, то в идеале получим четкую лесенку заданий. То же самое касается и реальной многопоточности. Любой код, и меня не убедят в обратном, выполняется строго линейно и последовательно. Если вызвана процедура или функция то код будет ждать ее завершения прежде чем перейти к следующему шагу. Так что в реальной многопоточности все происходит именно подобным образом. Но это так, отступление.

    Загрузку сервера я проверяю через библиотеку WMI методом Win32_Processor. Загрузку проверяет отдельное задание с периодичностью в три секунды (вычисляется эмпирическим путем), результат пишется в константу. Перед запуском очередного задания происходит считывание данных из константы. Если загрузка менее установленного лимита, то можно запускать очередное задание. Лимит так же подбирается с учетом того, что на определение загрузки процессоров так же нужно время, к сожалению оно занимает не доли секунд, и пока вычисляется загрузка процессоров важно не завалить сервер. Кратковременные пиковые загрузки вполне допустимы, если они сопоставимы с ожиданием на блокировках.

    Что касается применяемости, то один из вариантов я уже описал.

    Впрочем это один из главных разделов, где мы применяем распараллеливание. Я работаю на производственном предприятии со многими переделами и с параметрическими спецификациями (УПП 1.3). Задач, при которых требуется собрать состав большого количества изделий по всем переделам достаточно: расчет плановых цен, расчет потребностей под закупки, расчет загрузки оборудования, пересчет остатков материалов в конечную продукцию (обратная задача — сколько можно сделать из того, что имеем) и прочее и прочее. Применяем данный механизм и в анализе данных, в отчетах. В ближайшее время планируем переделать расчет себестоимости. Так же восстановление некоторых последовательностей выполняем в расспараллеленом режиме: по срезу каждой организации.

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

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

    Reply
  62. relanium86

    Да действительно если указать число итераций >= 10млн то фоновые задания ускоряют.

    Видимо сказывается то что требуется время на запуск фонового задания.

    Reply
  63. KroVladS

    (63) AlexBar,

    Отличная идея про загрузку сервера, по экспериментируем.

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

    не совсем понял как можно распараллелить по организациям?

    Reply
  64. DitriX
    Reply
  65. yuraos

    (65) KroVladS,

    наверное имется ввиду,

    что у последовательности есть измерение «Организация»

    и восстановление последовательности

    для каждого значения организации в ней

    можно попытаться запустить параллельно

    (для каждой организации в своем фоновом задании).



    если какие-то организации как-то взамимосвязаны

    по движениям в регистрах,

    то такой подход может оказатся не очень хорошим.

    Reply
  66. KroVladS

    (66) DitriX,

    если организации никак не связанны, то почему бы и нет

    (67) yuraos,

    если какие-то организации как-то взамимосвязаны

    по движениям в регистрах,

    то такой подход может оказатся не очень хорошим.

    Я лично не видел ни одной базы в которой ведётся учёт нескольких ни как не связанных организаций. Боле того я не могу представить ситуация при которой это было бы удобно.

    Собственно поэтому и задал вопрос.

    Опять же восстановление последовательностей — это перепроведение документов в хронологическом порядке,

    Из моего опыта при проведении до 50% времени уходит на запись в базу и на запросы с признаком «ДЛЯ ИЗМЕНЕНИЯ», в обоих случаях таблицы заблокированы до завершения транзакции. Тут не то что 10 потоков, даже 3 потока будут друг друга блокировать, не говоря о невозможности работать пользователям.

    Всё вышесказанное моё ИХМО, если я не прав пожалуйста покажите мне механизм с помощью которого я мог бы многопоточно восстанавливать последовательность партионного учёта в УТ 10.3.

    Reply
  67. AlexBar

    (66)

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

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

    перемещение между ними

    Сударь! Я списываю это выражение на то, что Вы пользуетесь своим сленгом, но постарайтесь подобного не произносить в присутствии бухгалтеров и аудиторов.

    Исходя из сказанного, если в какой-либо последовательности есть измерение Организация, то восстановление последовательностей в разрезе каждой организации можно вести «параллельно», желательно наложив управляемые блокировки на последовательность по данному измерению.

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

    Не совсем ясно к чему это относится.

    Согласитесь — метки немного искривляют линейность выполнения кода. Последовательно — да, но не линейно.

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

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

    Но в описываемом Вами примере есть положительное рациональное зерно: это может быть альтернативой фоновым заданиям в файловом режиме.

    Ага, и учесть последствия, а так же ограниченность платформы.

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

    Reply
  68. DitriX

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

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

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

    В случае ведения учета по РАУЗ — такой ситуации возникнуть не должно, хотя есть варианты.

    Сударь! Я списываю это выражение на то, что Вы пользуетесь своим сленгом, но постарайтесь подобного не произносить в присутствии бухгалтеров и аудиторов.

    Тут я согласен, почему то не дошли изменения комментария, я там дальше описывал ситуацию, которая заключалась в том, что если бы не документы перемещения, то и партии по каждому складу отдельно можно было бы выравнивать 🙂 К этому я и написал про перемещения. Разумеется перемещения между организациями быть в принципе не может, так как в документе стоит только одно поле Организация, а скады не связаны явно с организациями.

    Не совсем ясно к чему это относится.

    Это относится к тому — что далеко не все разумно решать распаралеливанием.

    Т.е. ситуации, когда один контекст ушел на метку, а второй контекст пошел дальше, в природе существовать не может.

    Я вам привел пример — когда может, и описал последствия 🙂

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

    И вообще 1С делает уже хорошие шаги в этом направлении, а именно — возможность регламентного запуска внешних обработок, без надобности лезть в конфигуратор, так сделано в УТ11, но там я еще толком не копался.

    З.Ы. Как по мне, так вся эта статья — стоила ваших комментариев 🙂

    (0) ты бы выудил что то из комментариев и обновил статью, тут комментариев на еще одну 🙂

    Reply
  69. AlexBar

    (70)

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

    Вот вам пример явной зависимости

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

    Это относится к тому — что далеко не все разумно решать распаралеливанием.

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

    P.S. Ваши комментарии так же не менее важны и информативны!

    Reply
  70. DitriX

    (71) считаю спор закрытым, и надеюсь увидиться с вами на конференции. Я думаю мы найдем что друг другу поведать 🙂

    Reply
  71. Fragster

    (68) KroVladS, Если у последовательности есть измерения — то запросто

    Reply
  72. Andreynikus

    (68) KroVladS,

    Я просто оставлю это здесь

    http://kb.1c.ru/articleView.jsp?id=72

    Reply
  73. KroVladS

    (74) Andreynikus,

    Спасибо конечно за ссылку, но:

    -надо было Апреля подождать для надёжности.

    -kb.1c.ru закрытый раздел для партнёров, я предполагаю что доступ туда есть только у процентов десяти пользователей инфостара.

    -основная идея в статье это разделить документы на независимые группы, при чём так чтобы группы не используются результаты проведения документов друг друга, и проводить их параллельно. Что для последовательности взаиморасчетов вполне реализуемо, а для моей проблемы «партионный учёт» в УТ 10.3 проблематично.

    Увидел ваш комментарий только сегодня, почему-то письмо с инфостара о комментариях перестали приходить.

    Reply
  74. efin

    В далеком 2008-м http://kb.mista.ru/article.php?id=696, автор я.

    Reply
  75. user645392_dimmkan

    (52)Насколько мне помниться из университетского курса по оптимизации операций — оптимальными для вычислений является количество потоков 2*e, т.е. 5-6.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *