Форум: "Базы";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.25;
Скачать: [xml.tar.bz2];




Вниз

TQuery.Prepare, сильные утечки памяти 


Antony   (2002-02-27 12:14) [0]

Привет, коллеги.

Нарыл очень неприятную хезу, связанную с Query.Prepare
Суть:
1)Есть некий параметризованный запрос
2)Делаю Prepare этого запроса - в самом начале работы
3)Работаю с запросом
3.1)устанавливаю параметр
3.2)делаю Open
3.3)читаю данные
3.4)делаю Close
4) В конце работы программы делаю UnPrepare

к пункту 3) в процессе работы обращаюсь некоторое, - достаточно большое,
колличество раз. После каждого прохода по 3) сильно растёт память(буквально
сотнями килобайт) и после Close не освобождается. Итого выходит что за день
работы у меня утекает порядка 70 Мегабайт, - удручающий показатель.
Самое интересное что даже в конце после UnPrepare память не освобождается,
и даже после Disconnect не освобождается.

Вот.

Если же не делать Prepare/UnPrepare то всё впорядке, память не растёт, и
всё внорме, кроме одного! - производительность выполнения запросов падает
на 25%,
это согласитесь не так уж и мало.

Перерыл доку по BDE - никаких объяснений не нашел, перерыл все настройки
BDE - тоже ничего не помогает. Работаю я с восьмым ораклом - но сомнительно
всё же чтобы это было как-то связано с ораклом.

Может быть кто-нибудь знает в чём тут дело и как это можно пофиксить?

Да, своих утечек нет, всё протестировал. Да вобщем-то потом просто написал
тестик который наглядно демонстрирует данную проблему:

unit main;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, datas;

type
TMainForm = class(TForm)
OutPut: TMemo;
PRFButton: TButton;
Button1: TButton;
Button2: TButton;
procedure PRFButtonClick(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
switch:boolean;
count:integer;
procedure HeepStatusSpool(Caption:String);
public
{ Public declarations }
end;

var
MainForm: TMainForm;

implementation
uses ShareMem;

{$R *.DFM}

procedure TMainForm.HeepStatusSpool(Caption:String);
var
HeapStatus:THeapStatus;
begin
HeapStatus:=ShareMem.GetHeapStatus();
with OutPut.Lines do
begin
Add("");
Add(Caption);
Add("---------------------------------------------------");
Add("TotalAllocated : "+IntToStr(HeapStatus.TotalAllocated));
Add("TotalFree : "+IntToStr(HeapStatus.TotalFree));
Add("TotalCommitted : "+IntToStr(HeapStatus.TotalCommitted));
Add("TotalUnCommitted : "+IntToStr(HeapStatus.TotalUnCommitted));
Add("TotalAddrSpace : "+IntToStr(HeapStatus.TotalAddrSpace));
Add("Overhead : "+IntToStr(HeapStatus.Overhead));
Add("Unused : "+IntToStr(HeapStatus.Unused));
Add("HeapErrorCode : "+IntToStr(HeapStatus.HeapErrorCode));
Add("===================================================");
Add("AllocMemCount : "+IntToStr(GetAllocMemCount()));
Add("AllocMemSize : "+IntToStr(GetAllocMemSize()));
Add("---------------------------------------------------");
end;
end;

procedure TMainForm.PRFButtonClick(Sender: TObject);
var
ST, FT:integer;
counter:integer;
begin
ST:=GetTickCount();
HeepStatusSpool("Start. GTC = "+IntToStr(ST));
for counter:=0 to count do
begin
switch:=not switch;
if switch then
DMP.PRQuery.ParamByName("TT").asString:="TABLE"
else
DMP.PRQuery.ParamByName("TT").asString:="VIEW";
DMP.PRQuery.Open;
while not DMP.PRQuery.Eof do DMP.PRQuery.Next;
DMP.PRQuery.Close;
end;
FT:=GetTickCount();
HeepStatusSpool("Start. GTC = "+IntToStr(FT)+" MUL = "+IntToStr(FT-ST));
end;

procedure TMainForm.Button1Click(Sender: TObject);
begin
DMP.PRQuery.Active:=False;
DMP.PRQuery.Prepare;
end;

procedure TMainForm.Button2Click(Sender: TObject);
begin
DMP.PRQuery.Active:=False;
DMP.PRQuery.UnPrepare;
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
switch:=true;
count:=1000;
end;

end.
_________________________________________________
В проекте должен быть дата модуль с названием DMP:TDataModule; в дата модуле
TSession TDataBase и запрос PRQuery [select TABLE_NAME from cat where TABLE_TYPE
= :TT]

на форме MainForm:TMainForm - три кнопки и OutPut:TMemo

запускаем TaskManager и наслаждаемся пейзажем :-))

Если будете юзать примерчик, то в проекте первым юнитом, должен быть воткнут ShareMem чтобы можно было пользоваться функциями
GetAllocMemCount();
GetAllocMemSize();

------------------------------------------------------------------------------------
program qp;

uses
ShareMem,
Forms,
main in "main.pas" {MainForm},
datas in "datas.pas" {DMP: TDataModule};

{$R *.RES}

begin
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.CreateForm(TDMP, DMP);
Application.Run;
end.



roottim   (2002-02-27 12:55) [1]

а ты не пробовал не в конце программы а после каждого закрытия вызывать метод UnPrepare!...
помоему они должны работать всегда в паре
как Open .. Close
так и Prepare .. UnPrepare



Antony   (2002-02-27 13:43) [2]

если так делать то пропадает всякий смысл в Prepare/UnPrepare
но понятно, что так всё нормально работает, только ещё дольше чем если бы я просто сделал Open/Close, такие пироги.



roottim   (2002-02-27 13:57) [3]

я так думаю смысл всего этого оптимизировать закачку большого НД... а не в скорости при открытии и закрытии НД




Форум: "Базы";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.03.25;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.73 MB
Время: 0.031 c
3-80429           new                   2002-02-26 10:35  2002.03.25  
Kak konetktirovat s MSSQL Server chtobi rabotal bistree?


1-80626           Eraser                2002-03-11 09:26  2002.03.25  
ско-ко размер файла


6-80643           Jorh                  2002-01-10 09:07  2002.03.25  
О параметре


6-80650           Chris                 2001-12-21 13:14  2002.03.25  
Открытые файлы с удаленного компа


3-80397           Demon ltd             2002-02-20 15:22  2002.03.25  
работа с Qreport ом