Out of Memory with Blob Fields

Discussion of open issues, suggestions and bugs regarding IBDAC (InterBase Data Access Components) for Delphi, C++Builder, Lazarus (and FPC)
Post Reply
Execute
Posts: 6
Joined: Tue 22 Jul 2014 22:56

Out of Memory with Blob Fields

Post by Execute » Fri 20 Mar 2015 14:03

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

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: Out of Memory with Blob Fields

Post by ViktorV » Tue 24 Mar 2015 09:54

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

Execute
Posts: 6
Joined: Tue 22 Jul 2014 22:56

Re: Out of Memory with Blob Fields

Post by Execute » Tue 24 Mar 2015 10:22

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

ViktorV
Devart Team
Posts: 3168
Joined: Wed 30 Jul 2014 07:16

Re: Out of Memory with Blob Fields

Post by ViktorV » Tue 24 Mar 2015 13:41

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

Post Reply