Ce veți învăța din acest articol?
- Veți explora opțiuni pentru accelerarea operațiilor de procesare a datelor
- Aflați cum puteți rula mai multe fire în 1C: Enterprise 8
- Aflați despre limitările multithreading în 1C
Periodic, este nevoie de accelerarea unor părți ale codului, în care, atunci când este fluent, nu există un potențial de accelerare.
Luați în considerare, de exemplu, încărcarea și / sau descărcarea unei cantități mari de date.
În acest caz, "bara de performanță" este adesea în mod direct performanța hardware-ului. În acest caz, procedurile de încărcare-descărcare ele însele se efectuează pentru o perioadă destul de lungă, adesea măsurate în ore.
Nu toată lumea știe că în platforma "1C: Enterprise 8", unele operațiuni pot fi efectuate în paralel. prin executarea simultană în fire multiple.
O astfel de prelucrare multi-filet este destul de aplicabilă în cazul în care este necesar să se proceseze blocuri de date independente. În special, creați o cantitate mare de elemente de date, efectuați executarea de documente care nu se suprapun cu valorile setului de măsurători, efectuați o actualizare masivă a intrărilor de directoare, încărcați datele în registre și așa mai departe.
De exemplu, ia în considerare sarcina: trebuie să actualizați recuzita "Pret" pentru toate elementele din directorul "Bunuri". Numărul de articole din directorul "Produse" este de 100.000.
Soluția cea mai simplă și cea mai evidentă este următorul cod de procesare, care este scris rapid, dar funcționează foarte mult timp:
Pe server
Actualizați prețul ()
Începeți ora = Data curentă ();
TableTables = Interogare Executa () Load ();
Durată = Data curentă () - Timp de începere;
Raport ("Durata:" + Durata + "sec.");
În cazul nostru, procesarea a fost efectuată în 1.187 secunde sau 19.7 minute.
Acum folosim execuția codului multi-threaded. Rescriem codul de procesare după cum urmează:
Pe server
Actualizați prețul ()
TableTables = Interogare Executa () Load ();
// determina numărul maxim de fire
Numărul de fluxuri = 8;
// cantitatea de date care trebuie procesată de fiecare fir
SizePorts = Țintă (numărul de rânduri din tabel / număr de fluxuri);
// o matrice în care vor fi stocate lucrări de fundal
Array of Tasks = Array nou;
Pentru numărul de flux = 1 după numărul de cicluri de curgere
// definiți indexul pentru a începe prelucrarea datelor cu acest flux
// diferite fire execută diferite părți ale tabelului
Index Start = (Numărul fluxului - 1) * Dimensiunea prețului;
Dacă (Numărul fluxului = Numărul de fluxuri) Apoi
// dacă acesta este ultimul fir, atunci procesează toate datele rămase
// din moment ce Numărul de fire nu poate fi un număr mai mare decât numărul de rânduri din tabel
SizePorts = Numărul de rânduri din tabel - (Număr de fire * Dimensiunea porturilor) + SizePorts;
Sfârșit Dacă;
// definiți matricea parametrilor pentru procedură
Set de parametri = Array nou;
SetParameters.Add (TableTables);
SetParameters.Add (Index Start);
SetParameters.Add (SizePorts);
// începeți lucrarea de fundal
Task = Assignments de fundal. Executați (set de parametri "Common Module1.Update the Price of the Product");
// adăugați lucrarea la matrice pentru a urmări execuția
Array de sarcini. Adăugați (Task);
// verificați rezultatul lucrărilor de fundal
În cazul matricei de modele. Numărul ()> 0 Apoi
încercare
Așteptări de așteptări pentru așteptări. Așteptați finalizarea (Entity Array);
Excepția
// acțiuni în caz de eroare
Încercări finale;
Sfârșit Dacă;
Durată = Data curentă () - Timp de începere;
Raport ("Durata:" + Durata + "sec.");
Codul modulului general:
Procedură: actualizați prețul produsului (tabel de vânzări, index, început, dimensiune, porțiuni) de export
Taxă suplimentară = 1,10; // taxă suplimentară de 10%
// actualizați prețul numai pentru o anumită parte a tabelului
Pentru Ct = 1 Prin ciclu SizeParts
Index =. (Ct = 1. Index de pornire, Index + 1);
În cazul nostru, au fost utilizate opt fire, actualizarea prețului a fost efectuată în 859 secunde sau 14,3 minute.
Adică, prelucrarea aceleiași tabele de valori în paralel cu diferite fire conduce la o creștere a vitezei.
Codul a fost rulat pe o mașină virtuală cu un procesor fără matrice RAID. Pe un "fier" real și bun, câștigul de viteză va fi mult mai mare.
Rețineți că această sarcină poate fi rezolvată într-un mod diferit, am dat doar un exemplu de implementare.
Important! Nu este nevoie să setați prea multe fire, deoarece nu veți obține o creștere rapidă a vitezei, iar stabilitatea muncii poate fi întreruptă.
Cel mai bun este utilizarea a 8-10 fluxuri, iar cantitatea lor optimă poate fi determinată experimental.
Încercați să efectuați un experiment, baza de date și prelucrarea pot fi descărcate aici.
Versiunea PDF a articolului pentru membrii grupului VKontakte
35 ore de pregătire, pregătire pentru 1C: Expert, configurarea corectă a părții de server, optimizarea codului, monitorizarea utilizării echipamentelor și alte lucruri adulte.
29 de răspunsuri la modul de accelerare 1C - procesarea datelor cu mai multe fire
Alo
Există o configurație cu acest cod: "Așteptări de fond, așteptați finalizarea", acest cod în fișierul de fișiere nu va funcționa deloc sau va funcționa foarte lent?
Problema este că atunci când începeți această metodă, nu există nici un proces de lucru vizibil: nici accesul la procesor, nici la fișiere nu se așteaptă mai mult de 20 de minute fără rezultate vizibile. Nu pot vedea sarcina de fond creată în configurator.
Am implementat metoda de bază pe serverul Sql pentru câteva minute.
Care ar putea fi problema?
Mulțumesc.
"Problemă" în baza de date a fișierelor, unde sarcina de fundal nu funcționează ca în versiunea client-server. Acest exemplu este pentru versiunea client-server.
Bună ziua!
Dacă această metodă este folosită pentru a paraleliza procesarea de valori mari de masă nu solicită un cod primit, creșterea disproporționată a volumului ocupat de memorie a fost văzută atunci când transferul la locul de muncă de fond, egal cu 2-3 volume de masă transmise, în timp ce în cazul în care locurile de muncă a alerga de fundal se întâmplă destul de des prin 2-3 zile, există o încetinire îngrijorătoare în procesele de lucru ale serverului de aplicații, salvează doar repornirea. Există o modalitate mai eficientă de a transfera datele într-o lucrare de fundal, fără a scrie în baza de date? Sau o modalitate de a face față creșterii și eliberării cantității de memorie ocupată?
De exemplu, optimizarea acestei situații este o parte integrantă a sarcinii finale a cursului de optimizare.
1. Există o modalitate mai eficientă de a transfera date într-o activitate de fundal, fără a fi scrisă în baza de date?
-
Poate că există, dar nu mă cunoaște. Deși nu văd nimic în neregulă cu ceea ce ar fi schimbarea unei părți a datelor pentru baza de date între FZ.
2. Sau o modalitate de a face față creșterii și eliberării cantității de memorie ocupată?
-
Cel puțin o recomandare standard, setați intervalul de repornire a proceselor de lucru 1 dată pe zi.
Da, există adesea mulți utilizatori nu sunt conștienți de elementarschinu - posibilitatea de a deschide mai multe sesiuni pentru a lucra cu baza de date, și să stea în dimineața înainte de prânz, de așteptare pentru repostarea trimestru sau formarea unui raport grele, sagely se uită cu ochii limpezi la monitor.
P.S. Strict vorbind, în ceea ce privește sarcina descrisă, cea mai rapidă (în practică, în zeci și adesea de sute de ori, depinde de date) va fi ceva de genul:
UPDATE _Reference53 SET _Fld9204 = _Fld9204 * (valoare coeficient) ;-))
Cred că experții prezenți aici vor fi de acord cu mine.
Din nefericire, platforma 1C nu implementează astfel de abordări, iar în sarcinile de schimbare a volumelor de date serioase este necesar să ieșim în acest fel. Timpul este o resursă costisitoare.
Sunt de acord cu dvs., bineînțeles prin interogări directe SQL ar fi mai rapid, de altfel, ar putea fi rulat în mai multe fire, dar sarcina este doar cum să o faci exclusiv prin 1C.
Metoda de mai sus nu este, de asemenea, cea mai optimă și una dintre sarcinile finale ale antrenamentului va fi optimizarea acestei metode.
Bună ziua. Organizarea prelucrării de date multi-rânduri pentru procesarea părții de masă a documentului. Prin optimizarea timpului este pur și simplu enorm. Dar! Funcția de fundal nu returnează date înapoi. (Este posibil pentru a obține într-un fel în jurul valorii de? Este posibil să se organizeze într-un fel valorile de retur de la locul de muncă de fundal pentru a permite valorile din tabel \ sau mai multe tabele, care sunt apoi combinate într-o singură, și va fi plasat într-un tabel al documentului?
Un exemplu puțin ușor convingător.
În acest caz, la 8 fluxuri, accelerația era de numai aproximativ 1,38. Dacă măsuram eficiența (raportul dintre accelerație și numărul de fluxuri), a fost doar 0,17. Până la 80% din efortul pe care l-am cheltuit pe cheltuieli generale.
Abordarea, desigur, este bună. Dar trebuie să alegeți o sarcină în care procesarea datelor din flux va dura mult mai mult decât lucrul cu cheltuielile aeriene. Apoi numerele vor fi mai frumoase, iar efectul efortului este palpabil.
Încă un lucru, atunci când rupem sarcina în părți separate, trebuie să ținem cont și de încărcarea uniformă a fiecărui fir. În caz contrar, eficiența noastră poate, de asemenea, să zboare către conductă.
Înțeleg că întrebarea mea va depăși tema subiectului, dar cred că este adecvată în cadrul acestei sarcini
De exemplu, ia în considerare sarcina: trebuie să actualizați recuzita "Pret" pentru toate elementele din directorul "Bunuri". Numărul de articole din directorul "Produse" este de 100.000.
Cum vă propuneți să organizați o tranzacție și capacitatea de a reveni dacă metoda este completată cu o eroare?
Corect, dacă greșesc, dar lucrările de fundal vor fi executate ca tranzacții izolate (în sesiuni separate).
Bună, Eugene!
Așa este, în acest caz, posibilitatea de a "întoarce" poate fi organizată numai independent, aceasta este o plată pentru paralelism.
Aici este necesar să ne gândim cu atenție, dar avem într-adevăr nevoie de o retrogradare, de exemplu, acest lucru nu este necesar pentru această sarcină.
În cazul unei erori, putem începe să procesăm din nou și produsele de la care prețul a fost deja actualizat nu vor fi actualizate.
În alte cazuri, puteți găsi diferite mecanisme de control.
"În cazul unei erori, putem începe să procesăm din nou, iar produsele de la care prețul a fost deja actualizat nu vor fi actualizate."
Pe ce temei în această procesare se stabilește că prețul a fost deja actualizat?
Bună ziua, Yuri!
Ultima dată când am răspuns în legătură cu o altă sarcină, când era necesar să procesăm bunurile, doar cu o anumită valoare a prețului.
Pentru această sarcină, va fi cu adevărat necesar să adăugați un semn că prețul a fost deja actualizat și că nu mai trebuie actualizat. Transacționalitatea va trebui să se facă independent.