Archived

This topic is now archived and is closed to further replies.

Allocating memory, how fast is it?

This topic is 4931 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, what''s faster, allocating an array statically inside a function ( double thearray[32] ), inside a function using new ( double *thearray=new double[32] ) and then delete it at the end of the function, using a global variable: double thearray[32]; void f(){ (... use it here ...) }; And also why of course... Thanks in advance.

Share this post


Link to post
Share on other sites
if you are using a global variable, then it is statically allocated, meaning at compile time. It would therefore be faster, as it would already be allocated when the program first runs. just to be sure put the static keyword in front of it.
One thing to be careful of though...that name will then be in the global namespace, so you might want to do this if it is in c++


namespace
{
static double thearray[32];
}

this will create an anonymous namespace, which has only file scope, and will prevent namespace pollution.

Share this post


Link to post
Share on other sites
I would not recommend the usage of global variables at all, only when its absolutly no other way. I consider massive use of global variables as bad programming, especially if you program c++.

While it might not seem to be wrong to use them in small programs, once your project gets bigger and more complex, global variables can become a source of ugly and hard to debug problems. Sooner or later you will lose track about all the places where you used that special variable.

About wether to use static or dynamic allocation inside a function, i would use static allocation over a new/delete in functions that are used alot. But keep in mind that if you use multithreading, this can lead to race-conditions.

Share this post


Link to post
Share on other sites
The global var is the fastest one. Beacuse it has the place in the .exe file and so, when the OS loads the .exe into the memory and runs it, there's a place for you variable. But as schue said - don't use it.

The stack (double thearray [32]) is slower than the global var, but faster than the new allocation. It simply substracts 256 from the esi and there's place in the stack created, ready to use. But, you might very easily get into the stack overflow, since it's not unlimited, and stack overflow is very horrible and painful bug.

The heap (double *thearray = new double [32]) is the slowest one. The program asks the system for some memory. The system then searches the memory to find some. When it's found, it's returned to your app. And when you stop using it, the app asks the system to mark it as free (the stack version, just adds 256 to the esi, removing the allocated space in one instruction). There's also a chance, the system doesn't give you the memory and then, you're in trouble, you have to solve. Also - using new and delete very often may lead to the heap fragmentation, causing next calls to new being very slow, or unsuccesful. But, at least, it doesn't cause stack overflow.

I would recommend you to use the stack version, if it's no too large. Or use the global var, if you don't have too many of them.

Oxyd

- Unreadable code is code written on a piece of paper, but not the one, in which the programmer is using a space in the place you don't.
- Real programmers aren't afraid of goto

[edited by - Oxyd on May 29, 2004 9:44:14 AM]

Share this post


Link to post
Share on other sites
Ok, thanks, i also noticed that if i declare variables at the beginning of a function it''s faster than when i declare them inside the scope of an if statement, why is that? Because the memory is only allocated then in a slower way because it''s not always needed (or are variables in the scope of a function allocated on startup)?

Share this post


Link to post
Share on other sites
The variables (stack ones) are created when you enter the scope. In C++ you may declare them wherever you want in the scope, but they exist since the entry of the scope:


void foo ()
{
doSomething ();
doYetMoreThings ();
int variable; //<- here, the variable is declared
//but exists since the '{'
somethingWithTheVar (variable);
}


And so, if you code "if (...) {" Then you create new scope (each '{' creates new scope) and so, new space on the stack must be created (and at the end it is destroyed). So if you have the 'if' inside some loop, the vars inside its scope are created and destroyed constantly, resulting in performance loss.


for (int i = 0; i < 10000; ++i) {
if (i % 2) { //if it's even
int var = i * i;
doSomethingWithTheResult (var);
}
}


This code constantly creates and destroys 'var' (5 000 times). If you put the int var before the for statement, it would be created only 1 time, which would be somewhat better.

Oxyd

- Unreadable code is code written on a piece of paper, but not the one, in which the programmer is using a space in the place you don't.
- Real programmers aren't afraid of goto

[edited by - Oxyd on May 29, 2004 12:47:38 PM]

[edited by - Oxyd on May 29, 2004 12:48:47 PM]

[edited by - Oxyd on May 29, 2004 12:49:30 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Hi Oxyd, so I thought about what you wrote about the variable being allocated in the scope of the block statement {}. I thought that most modern compiliers optimize the code so that variable is properly allocated in the stack without the need for continuous allocation/de-allocation.

Anyways, I tested a for-loop code on MS VC++ 6.0 and found that there is virtually no difference in speed.

- Steveo

Share this post


Link to post
Share on other sites
Oh, i think i meant that doing this:


for ( int i=0;i<100;i++){
//blablabla
};


is slower than:


int i;
for ( i=0;i<100;i++){
//blablabla
};


And that's something i still don't really get, it's probably because when variables are allocated there are certain tasks to be done before and/or after the allocation which only have to be done once when declaring the variable together with others at the beginning of the function. It does make a difference for sure (i tested it in release mode (maximize speed opt) and my app went from 89 to 92 fps when i replaced 2 variable allocations from statements to the beginning of the function scope, i know that framerate doesn't say much but is does say the difference is there).

Share this post


Link to post
Share on other sites
Quote:
Original post by Oxyd

The variables (stack ones) are created when you enter the scope. In C++ you may declare them wherever you want in the scope, but they exist since the entry of the scope:


Errm, I think you'll find this is horribly horribly wrong.
C++ doesnt construct a varible until it is used, which is a good plan as it can delay costly object construction until such time as it is needed, instead of constucting all the objects up front and having to destory them anyway even if you never use them.
Thus why you should delay declaring and constucting objects for as long as possible in C++ (iirc its one of the tips in either Effective C++ or More Effective C++).

With regards to the APs comment:
Objects are constucted/destory'd apon entry/exit of blocks in the majority of cases, namely things which are non-trival. For example you might be using a class in a loop which is allocated and adjusted as such when the loop finished the object has to be destoryed correctly and remade at the start of the next loop.
Granted, for things like int, floats, chars etc if MIGHT be able to get around it, depending on how its used, but for more complex objects the scopeing rules apply.

Share this post


Link to post
Share on other sites
Quote:
Original post by _the_phantom_
C++ doesnt construct a varible until it is used

If that's true i really really DON'T get the speed difference between the examples i gave above.

Share this post


Link to post
Share on other sites
Quote:
Original post by schue
I would not recommend the usage of global variables at all, only when its absolutly no other way. I consider massive use of global variables as bad programming, especially if you program c++.

While it might not seem to be wrong to use them in small programs, once your project gets bigger and more complex, global variables can become a source of ugly and hard to debug problems. Sooner or later you will lose track about all the places where you used that special variable.


I totally disagree.
Using global variables makes the debuging process FAR easier, as global variables are visible no matter where the program crashed, while the local variables are visible only in the function the program crashed.

Share this post


Link to post
Share on other sites
Quote:
Original post by _the_phantom_

Quote:
Original post by Oxyd

The variables (stack ones) are created when you enter the scope. In C++ you may declare them wherever you want in the scope, but they exist since the entry of the scope:


Errm, I think you'll find this is horribly horribly wrong.
C++ doesnt construct a varible until it is used, which is a good plan as it can delay costly object construction until such time as it is needed, instead of constucting all the objects up front and having to destory them anyway even if you never use them.
Thus why you should delay declaring and constucting objects for as long as possible in C++ (iirc its one of the tips in either Effective C++ or More Effective C++).

With regards to the APs comment:
Objects are constucted/destory'd apon entry/exit of blocks in the majority of cases, namely things which are non-trival. For example you might be using a class in a loop which is allocated and adjusted as such when the loop finished the object has to be destoryed correctly and remade at the start of the next loop.
Granted, for things like int, floats, chars etc if MIGHT be able to get around it, depending on how its used, but for more complex objects the scopeing rules apply.


A few weeks ago I decided to take a look at the ASM code of a simple C++ function (Reading an article about buffer overflow techniques), and I THOUGHT I saw everything on the stack created at function start. I'm not sure though (I'm no ASM guru, far from that).

But to comment on the initial post, tossing stuff on the stack is the fastest way. Inside your function do a "double[11]" and it will be put on the stack. This will often be in cached memory if I'm correct. If you make it global it will be put in heap memory, meaning that if you're unlucky it's not cached. Creating it with new is slowest, because at that point you're going to ask your OS for some memory. And you also need to free that memory again, so you're going to do a lot of work.

But I want to ask you this, what are you optimising? You're talking about differences in memory access speeds here.
If you're optimising some commonly used code (ie: often used maths code like cos/sin/vector stuff) then OK. But if this is about object management like loading textures or adding players it's a bit of an useless optimisation because it will be rarely used anyway (compared to your maths code for example).

Share this post


Link to post
Share on other sites
I have to agree with the above post. Why are you worrying about the speed of an array allocation? Unless you've reached the end of your project and have profiled it and found this to be a bottleneck then you don't need to consider optimising it. Premature optimisation is a very inefficient coding practice.

That being said I would recommend you use the following depending on situation:
Global variable: NEVER!!!! Global variables are evil (OK, saying they're evil is going a bit far, but I'm trying to make a point).
Stack based: For small fixed- and known-sized arrays only required in the current function.
Dynamically allocated: Never, see below.
std::deque or std::vector: All other cases. Deque's often have better performance when the array grows and shrinks because the memory does not have to be contiguous.

Enigma

Share this post


Link to post
Share on other sites
Quote:
Original post by Tree Penguin
Quote:
Original post by _the_phantom_
C++ doesnt construct a varible until it is used

If that's true i really really DON'T get the speed difference between the examples i gave above.


the speed difference you gave is pretty much a non-issue anyway (3fps isnt much, it would probably be covered by the error level with timing).

I've got a copy of Effective C++ infront of me now and, Item 32 on pg 135 "Postpone varible definitions as long as possible', says
Quote:

Remember that when you define a varible of a type with a constructor or deconstructor, you incur the cost of constrution when the control reaches the variable's definitions, and you incur the cost of destruction when the variable goes out of scope. This means there is a cost associated with unused varibles, so you want to avoid them whenever you can.


now, for something like an int the cost of construction on the stack is pretty much a case of sub 1 from the stack pointer and assign the point on the stack with the value given, deconstruction is just a case of adding back 1 to the stack pointer to remove the variable from scope. This is trivial work and shouldnt really be worried about for the most part its larger objects where things really make a difference which have complex (de)constructors.

As to the speed difference between code, thats as much down to the compiler, the settings used and even how the varible is used, as anything else.
In the for-loop example given the varaible 'i' in the first block of code is allocated, assigned and then deallocated when 'i' goes out of scope at the end of the loop.
The second code block allocated 'i', enters the loop scope, runs the loop and exits leaving the 'i' allocated on the stack (until such time it goes out of scope).
While the first version does a little more work you should pretty much ALWAYS use that version to prevent scoping issues with loop varibles.
for example:
- You declare 'i' at the top of the function or just outside the first loop it is used.
- you use 'i' in that loop
- you then use 'i' for something else later on without clearing it, this could lead to a bug which could take a while to track down, where as declaring it in the scope of the for loop instead throws a compiler error and makes you fix the code there and then.
You will see alot of code which uses the second way, this is because until recently the VC++ compile was broken and didnt respect the scoping rules correctly.

Share this post


Link to post
Share on other sites