Discussion:
Speed "problem" with SetLength
(too old to reply)
Skybuck Flying
2004-12-05 13:16:18 UTC
Permalink
Hi,

I might have a little speed "problem" with using dynamic arrays and
SetLength.

The SetLength routine calls FillChar to clear the contents of the dynamic
array.

In my case it is not necessary to clear the contents of the dynamic array
since it will be replaced anyway.

My concern is speed.

I need to allocate many dynamic arrays and then later "truncate" them.

This needs to happen as fast as possible.

There is a huge performance difference between getmem/freemem and setlength.

For example while benchmarking both. My PIII 450 mhz was able to
getmem/freemem 66000 bytes 30000 times per second.

While it was only able to setlength( 66000), setlength( 400) about 1800
times.

To make it completely fair I also tested:

SetLength( 66000 ) and
Buffer := nil;

Same result (only 1800 times)

Could borland please make a version of SetLength where the contents are not
cleared ?

For example SetLengthFast or so ?

or
SetLengthNoClear ;)

I might be able to make my own SetLengthFast version but then I would need
to know how to call it:

{ PROCEDURE _DynArraySetLength(var a: dynarray; typeInfo:
PDynArrayTypeInfo; dimCnt: Longint; lengthVec: ^Longint) }


_DynArraySetLength( MyArray, ?, ?, ? )

Bye,
Skybuck.
Skybuck Flying
2004-12-05 13:35:07 UTC
Permalink
Actually I wish I could simply "truncate" or "resize" the memory that was
allocated with getmem.

Then I wouldn't even need dynamic arrays.

Bye,
Skybuck.
Maarten Wiltink
2004-12-05 13:50:55 UTC
Permalink
Post by Skybuck Flying
Actually I wish I could simply "truncate" or "resize" the memory that was
allocated with getmem.
Like Realloc?

Groetjes,
Maarten Wiltink
Skybuck Flying
2004-12-05 15:17:59 UTC
Permalink
Post by Maarten Wiltink
Post by Skybuck Flying
Actually I wish I could simply "truncate" or "resize" the memory that was
allocated with getmem.
Like Realloc?
Ok, ReallocMem I think you mean ?

Indeed while inspecting the SetLength routine code I did notice some of
these Realloc things I think...

Though when going to delphi's getmem help... it's not mention.

"Dynamic allocation routines"

It is mentioned in:

"Memory management routines"

So apperently delphi has it's memory routines documentation a little bit
fragmented ;)

Ok that's more like it ;)

Now the performance is the same:

// GetMem( mBuffer, mMemorySize );
// FreeMem( mBuffer, mMemorySize );

ReallocMem( mBuffer, mMemorySize );
ReallocMem( mBuffer, 0 ); // ok ;)
mBuffer := nil;

Cool.

Thx Maarten

Bye,
Skybuck.
Skybuck Flying
2004-12-05 15:35:52 UTC
Permalink
Though one could ask the question:

Why is allocating/deallocating/resizing memory for small blocks fast and for
large blocks slow ?

( 500 bytes can be done 300.000 times per sec. 66000 bytes can be done
30.000 times per sec. om my computer )

It seems from inspecting the code... as long as the blocks are small only
delphi code is executed.

As soon as the blocks are large... it has to call kernel routines like
virtualAlloc... which is probably related to windows xp's memory manager...
and this memory manager is slower at allocating large blocks because it has
to search longer to find a large free block where the to be-allocated block
can fit into.

That would be my guess ;)

Bye,
Skybuck.
Peter Piper
2004-12-08 10:26:36 UTC
Permalink
What size are you defining as large and small memory sizes?
Post by Skybuck Flying
Why is allocating/deallocating/resizing memory for small blocks fast and for
large blocks slow ?
Skybuck Flying
2004-12-10 14:56:25 UTC
Permalink
500 small, 66000 large ;)
Post by Peter Piper
What size are you defining as large and small memory sizes?
Post by Skybuck Flying
Why is allocating/deallocating/resizing memory for small blocks fast and for
large blocks slow ?
J French
2004-12-05 16:13:39 UTC
Permalink
On Sun, 5 Dec 2004 14:16:18 +0100, "Skybuck Flying"
Post by Skybuck Flying
Hi,
I might have a little speed "problem" with using dynamic arrays and
SetLength.
The SetLength routine calls FillChar to clear the contents of the dynamic
array.
In my case it is not necessary to clear the contents of the dynamic array
since it will be replaced anyway.
My concern is speed.
I need to allocate many dynamic arrays and then later "truncate" them.
This needs to happen as fast as possible.
Is it not possible that if you are allocating and truncating many
Dynamic Arrays - PER SECOND - then perhaps you have chosen the wrong
design.

The FillChar is essential, because Dynamic Arrays can contain Strings.
If they were not zeroed, then destroying a Dynamic Array would have
some interesting side effects.

My guess is that you would be better off grabbing a chunk of memory
and 'managing' it yourself - but that is just a guess
Skybuck Flying
2004-12-05 22:50:59 UTC
Permalink
Post by J French
On Sun, 5 Dec 2004 14:16:18 +0100, "Skybuck Flying"
Post by Skybuck Flying
Hi,
I might have a little speed "problem" with using dynamic arrays and
SetLength.
The SetLength routine calls FillChar to clear the contents of the dynamic
array.
In my case it is not necessary to clear the contents of the dynamic array
since it will be replaced anyway.
My concern is speed.
I need to allocate many dynamic arrays and then later "truncate" them.
This needs to happen as fast as possible.
Is it not possible that if you are allocating and truncating many
Dynamic Arrays - PER SECOND - then perhaps you have chosen the wrong
design.
Actually I was re-thinking some design. The current design is very fast but
memory-wise inefficient.

This new design would be more memory efficient but a little bit slower ;)
How much slower it would be remains to be seen ;)
Post by J French
The FillChar is essential, because Dynamic Arrays can contain Strings.
If they were not zeroed, then destroying a Dynamic Array would have
some interesting side effects.
Yes I am aware of that, fortunately the contents do not contain strings ;)
Post by J French
My guess is that you would be better off grabbing a chunk of memory
and 'managing' it yourself - but that is just a guess
I also thought about this solution but that would be a *lot* of work
(writing one own's memory manager) and it would possibly not be any
faster... it could even be slower and at the end it would probably just be
re-inventing the wheel ;) so then I am better of using the build in memory
manager :)

( Also "just" grabbing a piece of memory could be dangerous as well because
one could run out of memory faster so to speak, that's another good reason
to choose for exisiting memory managers... all memory can be used... ;)
ofcourse suppose one has written it s own memory manager one could ofcourse
try and resize the big block of memory when an out of memory situation
arises ;) )

Bye,
Skybuck.
J French
2004-12-06 10:14:46 UTC
Permalink
On Sun, 5 Dec 2004 23:50:59 +0100, "Skybuck Flying"
<***@hotmail.com> wrote:

<snip>
Post by Skybuck Flying
Post by J French
The FillChar is essential, because Dynamic Arrays can contain Strings.
If they were not zeroed, then destroying a Dynamic Array would have
some interesting side effects.
Yes I am aware of that, fortunately the contents do not contain strings ;)
Dynamic Arrays are rather complex structures, personally I find them
very useful, but they are not really designed for rapid creation and
destruction.
Post by Skybuck Flying
Post by J French
My guess is that you would be better off grabbing a chunk of memory
and 'managing' it yourself - but that is just a guess
I also thought about this solution but that would be a *lot* of work
(writing one own's memory manager) and it would possibly not be any
faster... it could even be slower and at the end it would probably just be
re-inventing the wheel ;) so then I am better of using the build in memory
manager :)
I saw somewhere else that you had noticed that Delphi is much faster
at allocating and deallocating small chunks of memory than large
chunks.
I've not looked into this area in Delphi, but most languages grab
large chunks of memory from the OS and explicitly manage them
themselves. Malloc and Calloc come to mind
Post by Skybuck Flying
( Also "just" grabbing a piece of memory could be dangerous as well because
one could run out of memory faster so to speak, that's another good reason
to choose for exisiting memory managers... all memory can be used... ;)
ofcourse suppose one has written it s own memory manager one could ofcourse
try and resize the big block of memory when an out of memory situation
arises ;) )
I'm not so sure about that, if one truly needs a large amount of
memory then it is better to find out whether one has enough early on
in the App rather than 'fall off the perch' half way through a
routine.
AlanGLLoyd
2004-12-08 15:36:49 UTC
Permalink
Post by Skybuck Flying
Post by J French
My guess is that you would be better off grabbing a chunk of memory
and 'managing' it yourself - but that is just a guess
I also thought about this solution but that would be a *lot* of work
(writing one own's memory manager) and it would possibly not be any
faster... it could even be slower and at the end it would probably just be
re-inventing the wheel ;) so then I am better of using the build in memory
manager :)
Ray Lischner in Chap 19 of his book "Secrets of Delphi 2" discusses the details
of memory management, and provides a memory manager which improves on the
performance by calling win API directly.

Might be some useful information for you if you want to go this route.

Alan Lloyd
***@aol.com
Jud McCranie
2004-12-08 19:32:47 UTC
Permalink
On Sun, 5 Dec 2004 14:16:18 +0100, "Skybuck Flying"
Post by Skybuck Flying
This needs to happen as fast as possible.
While it was only able to setlength( 66000), setlength( 400) about 1800
times.
How many times do you need to be able to do this per second, and why?
You are probably better off extending a dynamic array by a good amount
rather than extending it by a small amount several times.
Post by Skybuck Flying
SetLength( 66000 ) and
SetLength( 66000) extends it by 66000 records, not 66000 bytes (unless
the record size is 1 byte).

---
Replace you know what by j to email
Skybuck Flying
2004-12-10 14:59:20 UTC
Permalink
Post by J French
On Sun, 5 Dec 2004 14:16:18 +0100, "Skybuck Flying"
Post by Skybuck Flying
This needs to happen as fast as possible.
While it was only able to setlength( 66000), setlength( 400) about 1800
times.
How many times do you need to be able to do this per second, and why?
You are probably better off extending a dynamic array by a good amount
rather than extending it by a small amount several times.
It's not being extended... it's being truncated the opposite ;)

About 1000 to 2000 in the future even 10000 to 20000 times ;)
Post by J French
Post by Skybuck Flying
SetLength( 66000 ) and
SetLength( 66000) extends it by 66000 records, not 66000 bytes (unless
the record size is 1 byte).
It's was an array of byte.

Anyway using getmem/freemem/reallocmem is a faster solution ;)

So I am pretty much done with this thread ;)

Bye,
Skybuck
Jud McCranie
2004-12-10 18:22:29 UTC
Permalink
On Fri, 10 Dec 2004 15:59:20 +0100, "Skybuck Flying"
Post by Skybuck Flying
It's not being extended... it's being truncated the opposite ;)
About 1000 to 2000 in the future even 10000 to 20000 times ;)
OK, why do you need to do that?

---
Replace you know what by j to email
Skybuck Flying
2004-12-10 20:22:37 UTC
Permalink
Post by Jud McCranie
On Fri, 10 Dec 2004 15:59:20 +0100, "Skybuck Flying"
Post by Skybuck Flying
It's not being extended... it's being truncated the opposite ;)
About 1000 to 2000 in the future even 10000 to 20000 times ;)
OK, why do you need to do that?
Lol, network packets ;)
Post by Jud McCranie
---
Replace you know what by j to email
Thaddy de Koning
2004-12-12 01:07:37 UTC
Permalink
Use a memorymanager replacement.
That's the cause of the speed problem (other than algoritm)
The DC-DSP audio components contain recyclerMM + fast Blockmove code
that can speed up an application over 20 times, depending code.
Recommended.


techinfo:

Delphi's default memory manager tries to re-use space from an internal
heap, thats why it is more efficient on smaller allocations.

Loading...