Page 1 of 1
Out of Memory with Blob Fields
Posted: Fri 20 Mar 2015 14:03
by Execute
Hi,
Using IBDAC 4.6.11 when I loop on a Query, the process memory usage grows until the close. The components uses defaults properties, the query is SELECT * FROM TABLE from a table with 4300 lines and a BLOB field that can contain up to 3Mb.
Same problem if I select only a INT field but with less impact.
Code: Select all
procedure TForm4.Button4Click(Sender: TObject);
begin
// 2 020K (in Windows process manager under Windows 7 32bits with Delphi XE3)
IBCConnection1.Database := dbName.Text;
IBCConnection1.Open;
IBCQuery3.Open;
while not IBCQuery3.Eof do
begin
IBCQuery3.Next;
end;
ShowMEssage('done1'); // 16 668K
IBCQuery3.Close;
ShowMEssage('done2'); // 6 564K
IBCConnection1.Close;
ShowMEssage('done3'); // 6 680K (?!)
end;
// 6 540K
Is that a known problem ?
Regards
Re: Out of Memory with Blob Fields
Posted: Tue 24 Mar 2015 09:54
by ViktorV
To decrease memory consumption when working with BLOB fields, you can set the DeferredBlobRead option of TIBCQuery to True.
DeferredBlobRead is used for fetching BLOB values when they are explicitly requested. You can find more information about the DeferredBlobRead option in the IBDAC documentation:
http://www.devart.com/ibdac/docs/devart ... obread.htm
Re: Out of Memory with Blob Fields
Posted: Tue 24 Mar 2015 10:22
by Execute
ok, but there still a problem.
I've just tried with last release 5.4 under Delphi XE7 and Windows 8.1
Code: Select all
procedure TForm1.Button1Click(Sender: TObject);
begin
IBCQuery1.SQL.Text := 'SELECT COUNT(*) FROM MYTABLE';
IBCQuery1.Execute;
ProgressBar1.Max := IBCQuery1.Fields[0].AsInteger;
ProgressBar1.Step := 1;
ProgressBar1.Position := 0;
IBCQuery1.SQL.Text := 'SELECT * FROM MYTABLE';
IBCQuery1.Execute;
while not IBCQuery1.Eof do
begin
ProgressBar1.StepIt;
Application.ProcessMessages;
IBCQuery1.Next;
end;
ShowMessage('Done1');
IBCQuery1.Close;
ShowMessage('Done2');
end;
the memory consumption still growing until the close without any memory leak.
In my case I went to an Out of Memory error before the end.
DeferredBlobRead partially resolve the problem, but there still a abnormal memory consumption when I do access the blob stream
Code: Select all
procedure TForm1.Button1Click(Sender: TObject);
var
blob: TField;
stream: TStream;
begin
IBCQuery1.SQL.Text := 'SELECT COUNT(*) FROM MYTABLE';
IBCQuery1.Execute;
ProgressBar1.Max := IBCQuery1.Fields[0].AsInteger;
ProgressBar1.Step := 1;
ProgressBar1.Position := 0;
IBCQuery1.SQL.Text := 'SELECT * FROM MYTABLE';
IBCQuery1.Execute;
blob := IBCQuery1.FieldByName('MYBLOB');
while not IBCQuery1.Eof do
begin
ProgressBar1.StepIt;
Application.ProcessMessages;
stream := IBCQuery1.CreateBlobStream(blob, TBlobStreamMode.bmRead);
AllocConsole;
WriteLn(Stream.Size); // without this, the stream seems to do nothing
stream.Free;
IBCQuery1.Next;
end;
ShowMessage('Done1');
IBCQuery1.Close;
ShowMessage('Done2');
end;
you probably have a kind of garbage collector for Blob streams that avoid memory leaks after the close, but I think that you should explicitly release things before that.
Regards
Re: Out of Memory with Blob Fields
Posted: Tue 24 Mar 2015 13:41
by ViktorV
You can also decrease memory consumption when reading records using the UniDirectional mode, that is designed for memory saving by unidirectional navigation through records. See more details about the UniDirectional mode in the IBDAC documentation:
http://www.devart.com/ibdac/docs/devart ... tional.htm