Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: Wangarad 18. 01. 2021, 16:04:21

Název: Python zrychlenie kódu
Přispěvatel: Wangarad 18. 01. 2021, 16:04:21
Zdravim akoby sa dalo zoptimalizovat toto? Mam cyklus kde pisem a citam data do 1.2s ale potreboval by som sa dostat pod 1.
Kód: [Vybrat]

for OPC_output in OPC_tag_list_output_array:
         value = '4:'
         tag_string = value + OPC_output
         #Load data from SQL
         SQL = "SELECT value FROM HMI.dbo.tag_list WHERE tag = '"+ OPC_output+"' "
         cursor.execute(SQL)
         result = cursor.fetchall()
         for row in result:
            SQL_Variable = row[0] 

             # Check if variable is string 
            OPC_Output_write = root.get_child(["0:Objects", "4:new_Controller_0", "3:GlobalVars", tag_string])
           # print("before: ", OPC_Output_write.get_value())
         if (SQL_Variable[0] == '1') or (SQL_Variable[0] == '0'):
             # print (SQL_Variable)
              if SQL_Variable == '1':
                  SQL_Variable = True
              if SQL_Variable == '0':
                  SQL_Variable = False     
              Variable = SQL_Variable
              OPC_Output_write.set_value(ua.DataValue(ua.Variant(Variable, ua.VariantType.Boolean)))
         else: 
              String_var = ua.DataValue(ua.Variant(SQL_Variable, ua.VariantType.String))
              OPC_Output_write.set_value(String_var)                           
Název: Re:Python zrychlenie kodu.
Přispěvatel: nehalem 18. 01. 2021, 16:12:34
Zdravim akoby sa dalo zoptimalizovat toto? Mam cyklus kde pisem a citam data do 1.2s ale potreboval by som sa dostat pod 1.
Kód: [Vybrat]

for OPC_output in OPC_tag_list_output_array:
         SQL = "SELECT value FROM HMI.dbo.tag_list WHERE tag = '"+ OPC_output+"' "
So zrychlenim ti neviem pomoct, ale toto vyzera na solidny SQL Injection. Ak si zaciatocnik doporucujem si to vygoolit a pochopit, preco je to zle. Kazdopadne nikdy neskladaj SQL dotazy tak, ze SQL dotaz tvoris spajanim s uzivatelskym vstupom, to je velke nie.

Ad zrychlenie, vidim, ze tam iterujes cez vysledky, keby som to robil ja, snazil by som sa urobit co najkonkretnejsi SQL dotaz ktory mi vrati idealne jeden konkretny alebo co najmensiu mnozinu vysledkov a vsetky tieto operacie delegovat na databazu, tie uz byvaju optimalizovane na rychle dotazovanie.
Název: Re:Python zrychlenie kódu
Přispěvatel: Kit 18. 01. 2021, 17:06:29
Co je zač ten objekt OPC_Output_write? Proč má tak divně pojmenované metody get_value() a set_value() a nemá třeba set_false(), set_true() a set_string()?

Nešlo by to celé udělat jedním trochu delším SQL dotazem?
Název: Re:Python zrychlenie kódu
Přispěvatel: Logik 18. 01. 2021, 17:08:58
Nejprve si zjisti (pomocí profileru), co vlastně trvá dlouho. Databáze?
Pak pomocí
Kód: [Vybrat]
WHERE tag IN ( ...,...,...,....) ORDER by tag to načti z DB najednou a zpracovávej to v Pythonu.Pokud sql dotaz trvá dlouho, tak Ti asi taky schází index na políčku tag v databázi?

Ale jinak je ten kód podivnej, co je např.
Kód: [Vybrat]
OPC_Output_write = root.get_child(["0:Objects", "4:new_Controller_0", "3:GlobalVars", tag_string]) To je nějaký lezení po stromě? Pak určitě se nemusí pokaždé lézt znovu z kořene, ne?
Název: Re:Python zrychlenie kódu
Přispěvatel: hechj 18. 01. 2021, 17:49:12
Databáze by měla vrátit co nejkonkrétnější výsledek, v ideálním tvaru, abys nemusel dělat podmínky jestli je nula nebo jedna. Vypadá to dost pitomě. IN ti dotaz nezrychlí. Otázka na strom je zajímavá. Jestli ho máš v databázi, rychlejší by bylo procházet ho v sql
Název: Re:Python zrychlenie kódu
Přispěvatel: Kit 18. 01. 2021, 18:19:19
Nejprve si zjisti (pomocí profileru), co vlastně trvá dlouho. Databáze?
Pak pomocí
Kód: [Vybrat]
WHERE tag IN ( ...,...,...,....) ORDER by tag to načti z DB najednou a zpracovávej to v Pythonu.

Že je IN ptákovinou, jsem zjistil po prvním benchmarku, ve kterém propadl.

Nejlepších výsledků jsem dosáhl, když jsem data nahrál do dočasné tabulky a provedl JOIN. Indexy zafungovaly a jelo to jako blesk.
Název: Re:Python zrychlenie kódu
Přispěvatel: Wangarad 18. 01. 2021, 19:59:53
nehalem lebo nacitavam do toho hodnoty s pola tak vzdy s tej slucky do adresy pridavam nazov noveho tagu. K tomu SQL viem ale to budem riesit ak budem v poslednom kroku.

Hechj tam je problemv tom ze v databazy je vsetko varchar(255) a s tym nepohnem. PLC chce obcas Int, obcas String takze musim nacitavat vzdy "string" a obcas tam je len 0 a PLC chce True or False

Logik : nie je tam asi 5000 premennych a ja musim citat zapisovat len konkretnu. S tymto si presne adresujes.






Název: Re:Python zrychlenie kódu
Přispěvatel: Kit 18. 01. 2021, 20:16:28
Co kdyby sis proměnnou OPC_tag_list_output_array uložil jako tabulku do databáze? Výstup všech hodnot získáš jedním dotazem.
Název: Re:Python zrychlenie kódu
Přispěvatel: Wangarad 18. 01. 2021, 21:55:12
Kit ale ten array uz mam nacitany s configu. Takze to mi velmi nepomoze.
Este som zmenil
Kód: [Vybrat]
   result = cursor.fetchall()
         for row in result:
            SQL_Variable = row[0]
na
Kód: [Vybrat]
   SQL_Variable = cursor.fetchone()[0] ale to mi pridalo 10ms na cyklus a stale potrebujem zobrat 400.
Název: Re:Python zrychlenie kódu
Přispěvatel: Kit 18. 01. 2021, 22:00:58
No tak to z configu nahrej do databázové tabulky. Bude to výrazně rychlejší.
Název: Re:Python zrychlenie kódu
Přispěvatel: Wangarad 18. 01. 2021, 22:39:58
Kit nerozumiem. Ako to myslis?

Mam tam slucku
Kód: [Vybrat]
for OPC_output in OPC_tag_list_output_array:
OPC_tag_list_output_array je uz pole ktore som naplnil ked sa spusta program a ide v loope. Ako mi pomoze ked budem este extra citat data s databazy? Alebo ako to myslis?
Název: Re:Python zrychlenie kódu
Přispěvatel: Logik 19. 01. 2021, 15:27:12
hejch:
Citace
. IN ti dotaz nezrychlí.
To bych se hádal. Načtění X záznamů z databáze najednou oproti načítání řádek po jednom zrychlí přístup do databáze v podstatě vždy. To je můj "denní chleba".

kit:
Citace
Že je IN ptákovinou, jsem zjistil po prvním benchmarku, ve kterém propadl.
Nejlepších výsledků jsem dosáhl, když jsem data nahrál do dočasné tabulky a provedl JOIN. Indexy zafungovaly a jelo to jako blesk.
Co já mám (s postrgresem) zkušenosti, tak hromadné načtení záznamů pomocí IN je vždy rychlejší, než načítání "po jednom", a nijak výkonnostně netrpí.Naházení do dočasné tabulky se dá udělat i jednodušeji pomocí
Kód: [Vybrat]
WITH data AS (
     VALUES (....),(...)
)
SELECT .....
ale nevidím důvod, proč by takovýto join měl proběhnout rychleji než operátor IN. Co jsem si teď zkusil na svejch malejch datech, tak IN byl rychlejší než JOIN (0.100-0.300ms versus 0.400-0.800ms), a lišili se i trochu v plánech (IN použil bitmap index scan, zatímco JOIN použil jen čistej index scan). Pokud jsem použil JOIN na temporary table, tak bez VACUUM ANALYZE na tu temporary table se použil sekvenční scan, po ANALYZE se použil stejnej plán, jako u JOINu na "WITH data AS ....".

Jaký výsledky a jaký plány to generuje Tobě?


Wangarg:
Citace
Kód: [Vybrat]
root.get_child(["0:Objects", "4:new_Controller_0", "3:GlobalVars", tag_string])
nie je tam asi 5000 premennych a ja musim citat zapisovat len konkretnu. S tymto si presne adresujes.
No podstata mého dotazu je, že začátek tý adresace je vždy stejný, takže by to mělo jít znova použít. Navíc, nejde náhodou o todle?
https://github.com/FreeOpcUa/python-opcua/
Pokud ano, tak opravdu po stromě lezeš (jen to nevíš :-)), takže můžeš na začátku vyselektit ten 3:GlobalVars a pak už jen hledat ten podřízenej nod podle tagu. Ale třeba se pletu?