Платформа 1С: Підприємство 8 володіє необхідними інструментами для забезпечення многопоточности, але на практиці про ці інструменти незаслужено забувають.
Звичайно, багатопоточність - це не панацея, але це хороший спосіб для:
1) зменшення тривалості виконання тривалих процедур (в деяких ситуаціях - на порядки!);
2) підвищення утилізації ресурсів обладнання.
Чи не кожну тривалу процедуру можна виконати в багатопотоковому режимі, а лише ті, які оперують великим числом невзаємопов'язаних блоків інформації.
1) Існує кілька сотень магазинів, що працюють на самопісний ПО, і єдина база в головній компанії, куди щодня вивантажуються транзакції з продажу. Завантаження ініціюється користувачем по кнопці і займає тривалий час, тому що магазинів багато і транзакцій пристойну кількість, а обробка пакетів даних йде послідовно.
У даній ситуації продажу кожного магазину не залежать один від одного, відповідно, сам розбір файлів і формування документів в системі можна виконати в багатопотоковому режимі. А ось проведення документів, швидше за все, буде вузьким місцем і має бути виконано в однопоточном режимі.
У цьому прикладі прискорення може бути не дуже великим, тому що формування документів займає менше часу, ніж їх проведення.
2) Існує велика база даних з транзакціями з продажу магазинів (з попереднього прикладі) і є необхідність періодично вивантажувати ці дані в сторонню BI-систему засобами 1С. Вивантаження ініціюється користувачем і займає тривалий час, тому що системі потрібно отримати з бази даних мільйони рядків і вивантажити їх у проміжну базу для BI. Під час вивантаження даних обладнання завантажено несуттєво.
У цій ситуації можна було б распараллелить вивантаження даних - одночасно вивантажувати дані по різних магазинах. Це істотно прискорить процес і дозволить повною мірою відчути ефект від потужного заліза.
Інструменти вбудованої мови для виконання багатопотокової процедури.
Найбільш ефективно організувати многопоточность можна за допомогою Фонових завдань (не плутати з регламентними завданнями).
Необхідно циклічно формувати порції фонових завдань і чекати їх завершення.
Приклад коду для другого випадку (вивантаження великого масиву даних порціями):
1) Процедура, яка ініціює багатопоточне виконання коду:
Процедура КнопкаВиполнітьНажатіе (Кнопка)
// вказує число потоків, які будуть запущені одночасно
ЧіслоПараллельнихПотоков = 10;
МассівЗаданій = Новий Масив;
Запит = Новий запит (
"ВИБРАТИ РІЗНІ
| ПартііТоваровНаСкладах.Склад
| З
| РегістрНакопленія.ПартііТоваровНаСкладах ЯК ПартііТоваровНаСкладах
| ДЕ
| ПартііТоваровНаСкладах.Період МІЖ Дата1 І Дата2 ");
Запит. УстановітьПараметр ( "Дата1". ДатаНачала);
Запит. УстановітьПараметр ( "Дата2". ДатаОкончанія);
Результат = Запит. Виконати (). Вивантажити ();
Для кожного Стор з Результат Цикл
МассівПараметров = Новий Масив;
МассівПараметров. Додати (ДатаНачала);
МассівПараметров. Додати (ДатаОкончанія);
МассівПараметров. Додати (Стор. Склад);
Завдання = ФоновиеЗаданія. Виконати ( "ВигрузкаДаннихНаСервере.ВигрузітьДанниеПоПартіям". МассівПараметров);
МассівЗаданій. Додати (Завдання);
Якщо МассівЗаданій. Кількість ()> = ЧіслоПараллельнихПотоков Тоді
спроба
ФоновиеЗаданія. ОжідатьЗавершенія (МассівЗаданій);
виняток
КонецПопиткі;
МассівЗаданій. Очистити ();
КонецЕсли;
Якщо МассівЗаданій. Кількість ()> 0 Тоді
спроба
ФоновиеЗаданія. ОжідатьЗавершенія (МассівЗаданій);
виняток
КонецПопиткі;
МассівЗаданій. Очистити ();
КонецЕсли;
Повідомити ( "Час виконання процедури -" + (ТекущаяДата () - ВремяНачала) + "с.");
2) Процедура, яку безпосередньо виконує фонове завдання (основна логіка):
Загальний модуль «ВигрузкаДаннихНаСервере», що виконується на сервері:
Процедура ВигрузітьДанниеПоПартіям (ДатаНачала. ДатаОкончанія. Склад) Експорт
Запит = Новий запит (
"ВИБРАТИ
| *
| З
| РегістрНакопленія.ПартііТоваровНаСкладах ЯК ПартііТоваровНаСкладах
| ДЕ
| ПартііТоваровНаСкладах.Період МІЖ Дата1 І Дата2
| І ПартііТоваровНаСкладах.Склад = Склад ");
Запит. УстановітьПараметр ( "Дата1". ДатаНачала);
Запит. УстановітьПараметр ( "Дата2". ДатаОкончанія);
Запит. УстановітьПараметр ( "Склад". Склад);
Результат = Запит. Виконати (). Вивантажити ();
Для кожного Стор з Результат Цикл
// Щось робимо з даними
КонецЦікла;
При цьому случає врахувати, що до вибору числа паралельних завдань потрібно поставитися відповідально - якщо запустити їх навіть кілька десятків, то велика ймовірність «повісити» і сервер додатків, і сервер СУБД.
66. Дмитро Шерстобитов (DitriX) 2525 16.04.13 12:37 Зараз в темі
(65) якщо організації ніяк не пов'язані, то чому б і ні, але якщо була хоча б одна продаж або переміщення між ними, то можуть бути ускладнення.
(63) може бути, однак є інший спосіб, більш надійний і простий, а ще й гнучкий, правда зі своїми нюансами, а саме - використання окремих регістрів для певних завдань.
Наприклад - є у мене УТ, там створюється дофіга чеків ККМ, чеки робляться зі складу з типом Оптовий (не питайте чому, так уже було і все обробки / звіти були заточені під це), і треба було вивантажувати інформацію з продажу.
Було 3 шляхи вирішення - робити вивантаження для кожного складу в своїх потоках, або бігти по ТЧ документів, або зробити окремий регист оборотів, куди вся інфа стікалася.
По зручності - був прийнятий третій варіант, так як він дозволив в підсумку в запитах дуже гарний об'єднаються з іншими даними і т.д.
Я до чого це - реальних завдань, які вимагають распаралеліванія - не так вже й багато, бо 90% проблем можна вирішити іншими шляхами з більш ізящьним підходом.
Будь-код, і мене не переконають у протилежному, виконується суворо лінійно і послідовно.
яке то розпливчасте трактування, в межах однієї інструкції, та й то, спірно, тому що є мітки.
Погодьтеся - мітки трохи викривляють лінійність виконання коду. Послідовно - так, але не лінійно.
Якщо викликана процедура або функція то код буде чекати її завершення перш ніж перейти до наступного кроку.
Та ну ладно вам так народ обманювати :)
Ось вам приклад реального распаралеліванія транзакцій:
Я Парс сайт, отримав 100 сторінок, мені треба їх розпарсити і помістити в регістр відомостей, наприклад, я отримую масив з 100 рядків, бігу по циклу і викликаю за допомогою vbs. Ось приклад:
Наприклад при натисканні на елемент.
Викликається клієнтської функція з неї ось ця:
Функція УточнітьДанние описанна в модулі обробки
І там же йде парсинг веб сторінок і додавання їх в дерево опису. Так ось, поки виконується ця функція - я можу спокійно працювати далі з обробкою і виконувати інші, не пов'язані з обробкою дерева - потоками.
Однак, як тільки я викличу ще раз цю функцію, і вона дійде до етапу відновлення дерева (при цьому перша ще не закінчилася), то вилітає в крит сама 1С.
Ось це - реально різні потоки, і ось до чого призводить їх застосування.
Однак, якщо я дані буду записувати в регістр, наприклад, а дерево зробити динамічним списком цього регістра - то все виходить ок.
Це я до чого - функція парсинга і т.д. ще виконується, але програма перейшла вже до іншої рядку коду, і не ждмет завершення попередньої функції, яка викликається з модуля.
Тобто реальних завдань насправді більш ніж достатньо, де можна застосувати цей механізм і прискорити роботу користувачів, потрібно просто включити фантазію.
Ага, і врахувати наслідки, а так само обмеженість платформи.
69. AlexBar (AlexBar) 52 17.04.13 00:31 Зараз в темі
якщо організації ніяк не пов'язані, то чому б і ні, але якщо була хоча б одна продаж або переміщення між ними, то можуть бути ускладнення.
Зовсім не ясно про яких зв'язках Ви говорите. Коли мова йде про Організацію, то однозначно йдеться про юридичну особу, так як для управлінського обліку поняття Організація в загальному випадку не існує. А раз мова йде про юридичну особу, то всі інші організації для цієї юридичної особи є всього лише контрагентами. І зовсім не важливо що між ними можуть бути перепродажу, давальницькі / комісійні / агентські схеми. Все це взаємини між Організацією та Контрагентом. Облік будь-якої організації є відокремленим і самодостатнім і не залежить жодним чином від інших організацій в базі даних.
переміщення між ними
Добродію! Я списую це вираз на те, що Ви користуєтеся своїм сленгом, але постарайтеся подібного не вимовляти в присутності бухгалтерів і аудиторів.
Виходячи зі сказаного, якщо в якій-небудь послідовності є вимір Організація, то відновлення послідовностей в розрізі кожної організації можна вести "паралельно", бажано наклавши керовані блокування на послідовність у даній виміру.
може бути, однак є інший спосіб, більш надійний і простий, а ще й гнучкий, правда зі своїми нюансами, а саме - використання окремих регістрів для певних завдань.
Не зовсім ясно до чого це відноситься.
Погодьтеся - мітки трохи викривляють лінійність виконання коду. Послідовно - так, але не лінійно.
Лінійність в моєму розумінні і в контексті того, що я говорю, означає буквально що код не може розгалузитися. Навіть дійшовши до позначки код перескочить на неї і почне відпрацьовувати вже від мітки. Тобто ситуації, коли один контекст пішов на мітку, а другий контекст пішов далі, в природі існувати не може.
Те, що Ви описуєте далі, я розумію як використання додаткових скриптів, які можуть виконуватися без очікування завершення виконання свого коду. Але це вже не контекст єдиного додатка. Та й рівносильно це тим же фоновим завданням, які ми розглядаємо. Ось тільки на відміну від скриптів фонові завдання виконуються в контексті все того ж додатка.
Але в описуваному Вами прикладі є позитивне раціональне зерно: це може бути альтернативою фоновим завданням у файловому режимі.
Ага, і врахувати наслідки, а так само обмеженість платформи.
Якщо бездумно махати сокирою, то помилок можна наробити і в простому математичному вираженні, яке геть завалить будь-який сервер.
67. Юрій Осипов (yuraos) 914 16.04.13 16:59 Зараз в темі
(65) KroVladS,
напевно мається на увазі,
що у послідовності є вимір "Організація"
і відновлення послідовності
для кожного значення організації в ній
можна спробувати запустити паралельно
(Для кожної організації в своєму фоновому завданні).
---
якщо якісь організації якось взамімосвязани
по рухах в регістрах,
то такий підхід може виявитися не надто хорошим.
59. Сергій Бушмакін (relanium86) 13 15.04.13 14:42 Зараз в темі
Дивно у мене вийшло следущую
Час виконання процедури - 102 с. з фонововимі
Час виконання процедури - 7 с. без фонових
Чому так цікаво?
60. Юрій Осипов (yuraos) 914 15.04.13 17:31 Зараз в темі
(59) relanium86,
розпаралелювання - не панацея,
це справа як Схід - тонка.
не всі завдання можна распараллелить взагалі
і оптимально распарралеліть зокрема.
61. Антон Грачов (Fragster) 745 15.04.13 18:04 Зараз в темі
(59) relanium86, самі по собі фонові завдання запускаються відчутний час, з цього для операцій <десятков секунд смысла вообще нет (или нужны постоянно запущенные задания "в боевой готовности")
64. Сергій Бушмакін (relanium86) 13 16.04.13 6:55 Зараз в темі
Так дійсно якщо вказати число ітерацій> = 10млн то фонові завдання прискорюють.
Мабуть дається взнаки те що потрібен час на запуск фонового завдання.
70. Дмитро Шерстобитов (DitriX) 2525 17.04.13 11:49 Зараз в темі
Зовсім не ясно про яких зв'язках Ви говорите. Коли мова йде про Організацію, то однозначно йдеться про юридичну особу, так як для управлінського обліку поняття Організація в загальному випадку не існує.
Якби ми знаходилися в америці або європі - я б теж посміявся, однак, були випадки коли люди продавали товар з однієї організації на одного, і робили це за собівартістю, але, так як партії не були вибудувана, то робили по будь-якими цінами, потім в кінці місяця вирівнювали партії, змінювалися ціни в документі реалізації і надходження на нову собівартість.
Ось вам приклад явної залежності, і поки одна організація дійшла до цього документа надходження - вона змушена ждвть поки друга організація дійде то пов'язаного документа продажу, що б там проставити ціни і перенеслися в надходження.
У разі ведення обліку по Рауза - такій ситуації виникнути не повинно, хоча є варіанти.
Добродію! Я списую це вираз на те, що Ви користуєтеся своїм сленгом, але постарайтеся подібного не вимовляти в присутності бухгалтерів і аудиторів.
Не зовсім ясно до чого це відноситься.
Це відноситься до того - що далеко не всі розумно вирішувати распаралеліваніем.
Тобто ситуації, коли один контекст пішов на мітку, а другий контекст пішов далі, в природі існувати не може.
Я вам навів приклад - коли може, і описав наслідки :)
А на рахунок висловленого вами обмеження - то я спочатку сказав, що тут треба уточнити - якщо в межах однієї функції - так, а якщо ні, то не вегда.
І взагалі 1С робить вже хороші кроки в цьому напрямку, а саме - можливість регламентного запуску зовнішніх обробок, без потреби лізти в конфігуратор, так зроблено в УТ11, але там я ще толком не копався.