Forum Delphi.cz

Delphi => FireDAC => Téma založeno: wajco 08-12-2015, 09:41:24

Název: firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 09:41:24
Pri pouziti Firedac pri volani fdquery.open v slucke nastava narast pamate konciaci Out of memory.Pri pouziti BDE zabera stale rovnaku pamat. odskusane to je s query umiestnenym na formulari aj s dynamicky vytvaranym query uvolnoenym voalni open. vyseldok je stale rovnaky. viete poradit nejaku property, ktora by to vyriesila, alebo ide o nejaky bug vo firedacu?

Kód: [Vybrat]

 while True do
    begin
      Randomize;
      FDQuery1.SQL.Text := 'select * from tab where i_tab='+Random(182064).tostring;
      inc(i);
      Label14.Caption := i.ToString();
      Application.ProcessMessages;
      Query1.Open;
    end;
Název: Re:firedac problem s pamatou
Přispěvatel: Radek Červinka 08-12-2015, 10:37:01
FDQuery1  versus Query1?

To je prepis?

Co je to za DB, co je to za driver?
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 10:41:31
FDQuery ma byt vsade, je to TFDQuery, db Informix, ovladac Infx [IBM INFORMIX ODBC DRIVER]
Název: Re:firedac problem s pamatou
Přispěvatel: pf1957 08-12-2015, 10:58:12
Kód: [Vybrat]

 while True do
    begin
      Randomize;
      FDQuery1.SQL.Text := 'select * from tab where i_tab='+Random(182064).tostring;
      inc(i);
      Label14.Caption := i.ToString();
      Application.ProcessMessages;
      Query1.Open;
    end;
Ja v tom vidim hned nekolik veci, z nichz mi vstava zbytek vlasu na hlave hruzou:
- opakovane uziti Randomize
- rucni matlani SQL dotazu misto pouziti parametrizovaneho dotazu, ktery by v konkretnim pripade umoznil pouzivat stale stejny SQL prikaz a jen menit hodnotu parametru v tele cyklu
- chybna prace s I/O prostredkem -> Po open nenasleduje Close, coz je nejspis pricina toho memory leaku. Spravne by tam melo byt
Kód: Delphi [Vybrat]
  1. Query1.Open;
  2. try
  3.   ...
  4. finally
  5.   Query1.Close;
  6. end
  7.  
Název: Re:firedac problem s pamatou
Přispěvatel: Stanislav Hruška 08-12-2015, 11:01:49
Nakoľko FireDAC používam, tak ma otázka zaujala. Pozrel som si vlastnosti FDQuery a zaujal ma DirectExecute. Chcel som si niečo o tom prečítať. Ako to vlastne funguje. Ale nič som nenašiel. A help k FireDAC nemá vyhľadávanie.
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 11:03:10
Kód: [Vybrat]

 while True do
    begin
      Randomize;
      FDQuery1.SQL.Text := 'select * from tab where i_tab='+Random(182064).tostring;
      inc(i);
      Label14.Caption := i.ToString();
      Application.ProcessMessages;
      Query1.Open;
    end;
Ja v tom vidim hned nekolik veci, z nichz mi vstava zbytek vlasu na hlave hruzou:
- opakovane uziti Randomize
- rucni matlani SQL dotazu misto pouziti parametrizovaneho dotazu, ktery by v konkretnim pripade umoznil pouzivat stale stejny SQL prikaz a jen menit hodnotu parametru v tele cyklu
- chybna prace s I/O prostredkem -> Po open nenasleduje Close, coz je nejspis pricina toho memory leaku. Spravne by tam melo byt
Kód: Delphi [Vybrat]
  1. Query1.Open;
  2. try
  3.   ...
  4. finally
  5.   Query1.Close;
  6. end
  7.  

1. close nepomaha, lebo prikaz open v sebe na zaciatku vola close
2. parametrizovane query nepomaha
3. randomize ma byt pred cyklom ano, ale toto tiez nepomoze

tu je upraveny kod, pamat stale narasta

Kód: [Vybrat]
procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
  q: TFDQuery;
begin
  i:= 0;
  Randomize;
  while True do
    begin
      FDQuery1.SQL.Text := 'select * from tab where i_tab=:p';
      FDQuery1.ParamByName('p').AsInteger := Random(182064);
      inc(i);
      Label14.Caption := i.ToString();
      Application.ProcessMessages;
      FDQuery1.Open();
    end;
end;
Název: Re:firedac problem s pamatou
Přispěvatel: Stanislav Hruška 08-12-2015, 11:08:42
Citace
close nepomaha, lebo prikaz open v sebe na zaciatku vola close
Ale určite sa nevolá, ak nie je dataset aktívny (iba moje presvedčenie).

Z praxe: ak používam parametrizovaný príkaz, tak pred priradením údajov do SQL (parametrov) musím najprv uzavrieť dataset. Ináč sa zmena neprejaví.
Název: Re:firedac problem s pamatou
Přispěvatel: Radek Červinka 08-12-2015, 11:10:37
a kdyz je ten select porad stejny?
select * from tab where i_tab= 10 ?
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 11:10:55
Citace
close nepomaha, lebo prikaz open v sebe na zaciatku vola close
Ale určite sa nevolá, ak nie je dataset aktívny (iba moje presvedčenie).

Z praxe: ak používam parametrizovaný príkaz, tak pred priradením údajov do SQL (parametrov) musím najprv uzavrieť dataset. Ináč sa zmena neprejaví.

z unitu FireDAC.Comp.Client

Kód: [Vybrat]
procedure TFDRdbmsDataSet.Open(const ASQL: String; const AParams: array of Variant;
  const ATypes: array of TFieldType);
var
  i: Integer;
begin
  Close;
  if ASQL <> '' then
    Command.SetCommandText(ASQL,
      not (Command.CommandKind in [skStoredProc, skStoredProcNoCrs, skStoredProcWithCrs]) and
      ResourceOptions.ParamCreate);
  if Command.CommandKind in [skStoredProc, skStoredProcNoCrs, skStoredProcWithCrs] then
    Prepare;
  if Params.BindMode = pbByNumber then
    for i := 0 to Params.Count - 1 do
      Params[i].Position := i + 1;
  for i := Low(ATypes) to High(ATypes) do
    if ATypes[i] <> ftUnknown then
      Params[i].DataType := ATypes[i];
  for i := Low(AParams) to High(AParams) do
    Params[i].Value := AParams[i];
  if not (Command.CommandKind in [skStoredProc, skStoredProcNoCrs, skStoredProcWithCrs]) then
    Prepare;
  Open;
end;
Název: Re:firedac problem s pamatou
Přispěvatel: Radek Červinka 08-12-2015, 11:11:29
a kdyz vyhodis Application.ProcessMessages; ?
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 11:12:15
a kdyz je ten select porad stejny?
select * from tab where i_tab= 10 ?

stale rovnaky vysledok:(
Název: Re:firedac problem s pamatou
Přispěvatel: Stanislav Hruška 08-12-2015, 11:13:37
 :)  Tak potom prečo sa tak správa? Rád by som to vedel.
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 11:14:17
a kdyz vyhodis Application.ProcessMessages; ?

nepomaha
Název: Re:firedac problem s pamatou
Přispěvatel: Radek Červinka 08-12-2015, 11:14:31
A jen pro zajímavost: kdyz das misto * nejaky konkretni sloupec?

Tohle znáš? http://delphi.cz/post/DDDebug.aspx (http://delphi.cz/post/DDDebug.aspx)
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 11:18:00
A jen pro zajímavost: kdyz das misto * nejaky konkretni sloupec?

Tohle znáš? http://delphi.cz/post/DDDebug.aspx (http://delphi.cz/post/DDDebug.aspx)

nad jednym stlpcom stupa pamat tiez, ale samozrejme pomalsie. mrknem na ten debugger
Název: Re:firedac problem s pamatou
Přispěvatel: pf1957 08-12-2015, 11:22:28
nad jednym stlpcom stupa pamat tiez, ale samozrejme pomalsie. mrknem na ten debugger
A v jakem stavu mas transakci? Nezustava ti otevrena a nesysluji se ti mak vsechna data?

My na vsech platformach a se vsemi typy RDMBS vzdycky cteme data pod explicitne nastartovanou a commitnutou read only transakci.
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 11:26:11
nad jednym stlpcom stupa pamat tiez, ale samozrejme pomalsie. mrknem na ten debugger
A v jakem stavu mas transakci? Nezustava ti otevrena a nesysluji se ti mak vsechna data?

My na vsech platformach a se vsemi typy RDMBS vzdycky cteme data pod explicitne nastartovanou a commitnutou read only transakci.

nerobim to v transakcii
Název: Re:firedac problem s pamatou
Přispěvatel: hlucheucho 08-12-2015, 11:28:07
"Sypeš to tam" aniž bys řešil odezvu DB. DB může dotaz zpracovávat delší dobu než za jakou vytvoříš a pošleš nový dotaz. Převzal bych přijatá data a pak bych poslal další dotaz. Obsluhuj události FDQuery (myslím AfterOpen). Takto jsem pracoval s MySQL, běželo to celý den bez nárůstu paměti.

Pokud používáš parametrický dotaz, SQLText stačí vytvořit jen jednou před vstupem do cyklu.

Komunikaci s DB může být vhodnější umístit do samostatného vlákna.

hu
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 11:34:11
"Sypeš to tam" aniž bys řešil odezvu DB. DB může dotaz zpracovávat delší dobu než za jakou vytvoříš a pošleš nový dotaz. Převzal bych přijatá data a pak bych poslal další dotaz. Obsluhuj události FDQuery (myslím AfterOpen). Takto jsem pracoval s MySQL, běželo to celý den bez nárůstu paměti.

Pokud používáš parametrický dotaz, SQLText stačí vytvořit jen jednou před vstupem do cyklu.

Komunikaci s DB může být vhodnější umístit do samostatného vlákna.

hu

v BDE to ide  bez narastu pamati, to len firedac ma takyto problem
Název: Re:firedac problem s pamatou
Přispěvatel: hlucheucho 08-12-2015, 11:39:57
Když posílám select, očekávám data. Kromě dotazů se tam mohou hromadit i přijatá data. Vždycky jsem zpracoval odezvu DB a neměl jsem problém s Memory Leak ani u FireDAC.

hu
Název: Re:firedac problem s pamatou
Přispěvatel: pf1957 08-12-2015, 11:50:40
nerobim to v transakcii
No to neni zcela urcite pravda - komunikace s RDMBS urcite pod nejakou transakci bezi. Takze pouzivas nejakou default txn z FireDac, ktera je buhvi jak nastavena.

Osobne bych doporucoval transakce neignorovat a i kdyz je to nepohodlne, tak si je pekne explicitne ridit.
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 11:57:45
nerobim to v transakcii
No to neni zcela urcite pravda - komunikace s RDMBS urcite pod nejakou transakci bezi. Takze pouzivas nejakou default txn z FireDac, ktera je buhvi jak nastavena.

Osobne bych doporucoval transakce neignorovat a i kdyz je to nepohodlne, tak si je pekne explicitne ridit.

tak jedine nastavenie txOptions ktore som zmenil su DisconnectAction xdRollback a Isolation xiDirtyRead



Název: Re:firedac problem s pamatou
Přispěvatel: pf1957 08-12-2015, 12:03:51
v BDE to ide  bez narastu pamati, to len firedac ma takyto problem
S BDE bych zrovna nic nesrovnaval, tak je spis divne, ze to vubec neco dela :-)

BTW, jaky je smysl dotazu, ktery nic s vytazenymi daty nedela? Normalne by za open nasledovalo neco jako
Kód: Delphi [Vybrat]
  1. Query1.Open;
  2. while not Query1.Eof do
  3.   begin
  4.      .... Query.Fields[x].AsXxxx;
  5.      Query1.Next;
  6.   end;
  7.  
Název: Re:firedac problem s pamatou
Přispěvatel: Stanislav Hruška 08-12-2015, 12:04:25
No, kompletný kód by mal byť takýto:
Kód: Delphi [Vybrat]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var i: Integer;
  3.   q: TFDQuery;
  4. begin
  5.   i:= 0;
  6.   Randomize;
  7.   q := TFDQuery.Create(self);
  8.   q.Connection := SomeConnection;
  9.   q.Trnasaction := SomeBasicTransaction;
  10.   q.SQL.Text := 'select * from tab where i_tab = :p';
  11.  
  12.   while True do
  13.     begin
  14.       q.Close:  // Moja skúsenosť.
  15.       q.ParamByName('p').AsInteger := Random(182064);
  16.       inc(i);
  17.       Label14.Caption := i.ToString();
  18.       Application.ProcessMessages;
  19.       q.Open();
  20.     end;
  21. end;
  22.  
Predpokladám, že to je len tak narýchlo čosi čiastočne opísané. Ako by som to robil ja ;)
Osobne ma zaujíma, že ak dáš
Kód: Delphi [Vybrat]
  1. Label14.Caption := i.ToString() + ' - ' + SomeField.AsString;
  2.  
či sa bude meniť hodnota poľa.
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 12:06:53
v BDE to ide  bez narastu pamati, to len firedac ma takyto problem
S BDE bych zrovna nic nesrovnaval, tak je spis divne, ze to vubec neco dela :-)

BTW, jaky je smysl dotazu, ktery nic s vytazenymi daty nedela? Normalne by za open nasledovalo neco jako
Kód: Delphi [Vybrat]
  1. Query1.Open;
  2. while not Query1.Eof do
  3.   begin
  4.      .... Query.Fields[x].AsXxxx;
  5.      Query1.Next;
  6.   end;
  7.  
to je len ilustracny priklad
Název: Re:firedac problem s pamatou
Přispěvatel: pf1957 08-12-2015, 12:12:24
to je len ilustracny priklad
To je sice vyborny, ale na zaklade ceho myslis, ze dostatnes relevantni odpoved, kdyz jsi apriory udelal rozhodnuti o tom, kde ten memory leak urcite neni  :o
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 12:22:26
to je len ilustracny priklad
To je sice vyborny, ale na zaklade ceho myslis, ze dostatnes relevantni odpoved, kdyz jsi apriory udelal rozhodnuti o tom, kde ten memory leak urcite neni  :o

ved som skusil spustit len tento zdrojak a som videl ako mi pamat stupa, tak naco tam budem dohadzovat ostatny kod...
Název: Re:firedac problem s pamatou
Přispěvatel: pf1957 08-12-2015, 12:28:34
ved som skusil spustit len tento zdrojak a som videl ako mi pamat stupa, tak naco tam budem dohadzovat ostatny kod...
No protoze ten kod ma - eufemisticky receno - spekulativni charakter a jak jsem prubezne psal, vykazuje radu vlastnosti, ktere se mi nelibi a ktere bychom nikdy nenapsali. A protoze pouzivame databaze zpusobem, jaky se predpoklada, tak jsme nikdy nehonili takovouhle ducharinu. A pod FireDac jsem pred lety portoval docela rozsahlou rodinu aplikaci z FIB+, kterou jsem ani sam nepsal. A na zadne problemy si nepamatuju.

Proto by mne zajimalo, jak se to bude chovat, kdyz se s tim pracuje radnym zpusobem.
Název: Re:firedac problem s pamatou
Přispěvatel: hlucheucho 08-12-2015, 13:23:31
V obsluze události kliknutí na tlačítko bych si odpustil nekonečnou smyčku a ProcessMessage. Opakování select jde udělat i bez nich.

hu
Název: Re:firedac problem s pamatou
Přispěvatel: wajco 08-12-2015, 13:54:49
V obsluze události kliknutí na tlačítko bych si odpustil nekonečnou smyčku a ProcessMessage. Opakování select jde udělat i bez nich.

hu
nekonecna slucka je na znazornnie kvoli tej narastajucej pamati
process je kvoli refreshu labelu