Subject | RE: [firebird-support] Memory allocation problem in Firebird 2.1.2 |
---|---|
Author | Calin Pirtea |
Post date | 2009-08-18T10:14:03Z |
Hi Dmitry,
Thanks for your response. I double checked our UDF and it was using the
wrong memory allocation inside the UDF. I fixed it and it works
perfectly.
This means we now have a work around and I can breathe... J
I am still interested in paying a small amount for a developer to work
towards fixing this inside the engine if you do consider it as important
as I do...
Thanks a million Dmitry.
Here is the code of my UDF written in Delphi 2007:
MaxVarCharSize = 32764;
TVarCharData = array[1..MaxVarCharSize] of char;
TVarChar = record
length: smallint;
data: TVarCharData;
end;
PVarChar = ^TVarChar;
function MakeVarChar(aStr: string; iLen: integer = 254): PVarChar;
var
LLen: longint;
MaxLen: integer;
Str: string;
begin
{The maximum length for the varchar we are going to allow is the
smaller of
1. the iLen argument passed to the function.
2. the maximum size allowed in memory for our own definition of
varchars}
MaxLen := Min(iLen, Pred(SizeOf(TVarCharData)));
Str := aStr;
LLen := Length(Str);
if LLen > MaxLen then
begin
LLen := MaxLen;
Str := Copy(aStr, 1, MaxLen);
end;
Result := ib_util_malloc(MaxLen + 3);
EmptyMem(Result, MaxLen + 3);
Result.Length := LLen;
if LLen > 0 then
BlockCopyMem(@Str[1], @..., LLen);
end;
function BlobAsString(Blob: PBlob): string;
var
bytes_read, bytes_left, total_bytes_read: Longint;
st: string;
begin
result := '';
if (not Assigned(Blob)) or
(not Assigned(Blob^.BlobHandle)) then
exit;
with Blob^ do
begin
bytes_left := TotalSize; // I have TotalSize bytes to read.
if (bytes_left = 0) then // if I've nothing to copy, exit.
exit;
SetLength(st, TotalSize);
total_bytes_read := 0; // total bytes read is 0.
repeat
// Using BlobHandle, store at most "bytes_left" bytes in
// the buffer starting where I last left off
GetSegment(BlobHandle, @st[total_bytes_read + 1], bytes_left,
bytes_read);
bytes_read := (bytes_read and $FFFF);
// Increment total_bytes_read by the number of bytes actually
read.
Inc(total_bytes_read, bytes_read);
// Decrement bytes_left by the number of bytes actually read.
Dec(bytes_left, bytes_read);
until bytes_left <= 0;
end;
Result := st;
end;
function CU_BLOBSUBSTRING(aBlob: PBlob; iFrom: Psmallint; iFor:
Psmallint): PVarChar;
var
aFrom, aFor: integer;
aString, aStr: string;
begin
Result := nil;
if (not Assigned(aBlob)) or (not Assigned(aBlob^.BlobHandle)) then
exit;
if (iFrom = nil) or (iFor = nil) then
exit;
aFrom := iFrom^;
aFor := iFor^;
aString := BlobAsString(aBlob);
if aFor > 32764 then
aFor := 32764;
if (aFrom + aFor - 1) > Length(aString) then
aFor := (Length(aString) - aFrom) + 1;
{If the parameters passed are outside the string then return an empty
string.}
if (aFor < 1) or (aFrom > Length(aString)) then
begin
aFor := 0;
aFrom := 1;
end;
try
SetLength(aStr, aFor);
if aFor > 0 then
BlockCopyMem(@aString[aFrom], @aStr[1], aFor);
except
end;
Result := MakeVarChar(aStr);
end;
The error in the UDF was that instead of SetLength, the programmer
incorrectly used SetString which causes a memory leak outside Firebird
memory manager's control.
Cheers,
Calin Pirtea
Communicare Development Team
Communicare Systems Pty Ltd
Tel: 9332 2433 Fax: 9310 1516
calin.pirtea@...
<mailto:calin.pirtea@...>
www.communicaresystems.com.au <http://www.communicaresystems.com.au>
Communicare Systems advises that this email account is not continuously
monitored. Please forward any Helpdesk enquiries to our monitored
address helpdesk@...
<mailto:helpdesk@...> and note that urgent
matters must be advised by telephone. This message, and any
attachments, are intended only for the use of the individual or entity
to which it is addressed and may contain information that is
confidential. Any unauthorised use, disclosure, reproduction or
distribution of this message and its attachments is prohibited. This
message is forwarded from an individual and does not necessarily
represent the views of Communicare Systems. If you have received this
message in error kindly notify the sender and then delete the contents.
From: firebird-support@yahoogroups.com
[mailto:firebird-support@yahoogroups.com] On Behalf Of Dmitry Yemanov
Sent: Tuesday, 18 August 2009 3:52 PM
To: firebird-support@yahoogroups.com
Subject: Re: [firebird-support] Memory allocation problem in Firebird
2.1.2
Calin Pirtea wrote:
fbserver process didn't grow during the query execution. Maybe it's
worth discussing your UDF code?
Dmitry
[Non-text portions of this message have been removed]
Thanks for your response. I double checked our UDF and it was using the
wrong memory allocation inside the UDF. I fixed it and it works
perfectly.
This means we now have a work around and I can breathe... J
I am still interested in paying a small amount for a developer to work
towards fixing this inside the engine if you do consider it as important
as I do...
Thanks a million Dmitry.
Here is the code of my UDF written in Delphi 2007:
MaxVarCharSize = 32764;
TVarCharData = array[1..MaxVarCharSize] of char;
TVarChar = record
length: smallint;
data: TVarCharData;
end;
PVarChar = ^TVarChar;
function MakeVarChar(aStr: string; iLen: integer = 254): PVarChar;
var
LLen: longint;
MaxLen: integer;
Str: string;
begin
{The maximum length for the varchar we are going to allow is the
smaller of
1. the iLen argument passed to the function.
2. the maximum size allowed in memory for our own definition of
varchars}
MaxLen := Min(iLen, Pred(SizeOf(TVarCharData)));
Str := aStr;
LLen := Length(Str);
if LLen > MaxLen then
begin
LLen := MaxLen;
Str := Copy(aStr, 1, MaxLen);
end;
Result := ib_util_malloc(MaxLen + 3);
EmptyMem(Result, MaxLen + 3);
Result.Length := LLen;
if LLen > 0 then
BlockCopyMem(@Str[1], @..., LLen);
end;
function BlobAsString(Blob: PBlob): string;
var
bytes_read, bytes_left, total_bytes_read: Longint;
st: string;
begin
result := '';
if (not Assigned(Blob)) or
(not Assigned(Blob^.BlobHandle)) then
exit;
with Blob^ do
begin
bytes_left := TotalSize; // I have TotalSize bytes to read.
if (bytes_left = 0) then // if I've nothing to copy, exit.
exit;
SetLength(st, TotalSize);
total_bytes_read := 0; // total bytes read is 0.
repeat
// Using BlobHandle, store at most "bytes_left" bytes in
// the buffer starting where I last left off
GetSegment(BlobHandle, @st[total_bytes_read + 1], bytes_left,
bytes_read);
bytes_read := (bytes_read and $FFFF);
// Increment total_bytes_read by the number of bytes actually
read.
Inc(total_bytes_read, bytes_read);
// Decrement bytes_left by the number of bytes actually read.
Dec(bytes_left, bytes_read);
until bytes_left <= 0;
end;
Result := st;
end;
function CU_BLOBSUBSTRING(aBlob: PBlob; iFrom: Psmallint; iFor:
Psmallint): PVarChar;
var
aFrom, aFor: integer;
aString, aStr: string;
begin
Result := nil;
if (not Assigned(aBlob)) or (not Assigned(aBlob^.BlobHandle)) then
exit;
if (iFrom = nil) or (iFor = nil) then
exit;
aFrom := iFrom^;
aFor := iFor^;
aString := BlobAsString(aBlob);
if aFor > 32764 then
aFor := 32764;
if (aFrom + aFor - 1) > Length(aString) then
aFor := (Length(aString) - aFrom) + 1;
{If the parameters passed are outside the string then return an empty
string.}
if (aFor < 1) or (aFrom > Length(aString)) then
begin
aFor := 0;
aFrom := 1;
end;
try
SetLength(aStr, aFor);
if aFor > 0 then
BlockCopyMem(@aString[aFrom], @aStr[1], aFor);
except
end;
Result := MakeVarChar(aStr);
end;
The error in the UDF was that instead of SetLength, the programmer
incorrectly used SetString which causes a memory leak outside Firebird
memory manager's control.
Cheers,
Calin Pirtea
Communicare Development Team
Communicare Systems Pty Ltd
Tel: 9332 2433 Fax: 9310 1516
calin.pirtea@...
<mailto:calin.pirtea@...>
www.communicaresystems.com.au <http://www.communicaresystems.com.au>
Communicare Systems advises that this email account is not continuously
monitored. Please forward any Helpdesk enquiries to our monitored
address helpdesk@...
<mailto:helpdesk@...> and note that urgent
matters must be advised by telephone. This message, and any
attachments, are intended only for the use of the individual or entity
to which it is addressed and may contain information that is
confidential. Any unauthorised use, disclosure, reproduction or
distribution of this message and its attachments is prohibited. This
message is forwarded from an individual and does not necessarily
represent the views of Communicare Systems. If you have received this
message in error kindly notify the sender and then delete the contents.
From: firebird-support@yahoogroups.com
[mailto:firebird-support@yahoogroups.com] On Behalf Of Dmitry Yemanov
Sent: Tuesday, 18 August 2009 3:52 PM
To: firebird-support@yahoogroups.com
Subject: Re: [firebird-support] Memory allocation problem in Firebird
2.1.2
Calin Pirtea wrote:
>2GB
> That was my first try. Unfortunately it is a lot worse. It allocates
> of RAM and that keeps on working corrupting memory. Scary stuff.Hmmm. I draftly tried that before suggesting and the memory of the
fbserver process didn't grow during the query execution. Maybe it's
worth discussing your UDF code?
Dmitry
[Non-text portions of this message have been removed]