To STATIC or not to STATIC...

Member
Posts: 48
Joined: 2009.05
Post: #1
Hello.

I've got a question that's been bugging me for weeks, and I think I've now got to a point where I'm confusing myself more by self-investigation, than I would be by just asking the question aloud so here goes...

I'm a Uni student, who previously to my current project have worked on the MS Desktop platform using C++ / OpenGL (Desktop) and a little DX9.

This last year I've been on a Masters of Science course in Games Programming at one of the most recognised and reputed Universities in the UK for such a course and most of our grad's get jobs directly into the major games houses, both in the UK and abroad.

I'm saying all this, because I want to convey not only my experience, but of the high level of competency and quality of my lecturers and the course content.

For our first piece of assessed coursework (ACW) we had to code from the ground up a 3d racing game in the vein of scalextrix with a dynamic and user created track, multiple views, particles systems, reflections, shaders etc...in 12 weeks.

It was during this piece of ACW and my understanding of how to 'code correctly' that I bumped into the issue I'd like some help with.

In C++ I would use lots of instance (object) variables and have them initialized in the INITIALIZATION LIST in the constructor. As this is the quickest and most optimal way of doing things.

However, sometimes, when only a single method (that might be called repeatedly during each frame) would need a variable I declared that variable as a static variable LOCAL to that method.

When it came to marking my ACW, I was informed that that was an inefficient and slow way to do things, by the department head. And yet, I'd seen other students and graduates do the exact same thing. I thought it was good practice and efficient.

The reasons the lecturer gave to change my mind on this was as follows:

1. Static declared variables (regardless of them being instance or local to a method) are stored on the HEAP. Non static are stored on the STACK.

2. When the method is loaded into L1 cache, all of it's variables are copied in too (assuming available space), however, because the STATIC variable is on the HEAP, then a memory call is made to fetch that data, that goes from L1 cache, to L2 cache (to see if they are there), then to L3 cache (if available and as before) and then finally out to main memory (HEAP)

All of these calls to the next level of cache/memory is a huge order of magnitude slower than the previous cache's performance.

So therefore don't use STATIC for variables that are needed in the 'render' loop.

With me so far?

Now skip forward 9 months, and I'm writing my first iPhone game, and first anything on the Apple Mac platform, and I bump into STATIC LOCALLY DECLARED vertex, color, normal and texture arrays.

This seems the antithesis of everything I learnt before.

However, the only reason I can possible see for this being the case, is that unlike a desktop processor that does not have unified ram and has multiple levels of cache memory etc, the ARM processor and the PowerVR MBX chip (SBX too?) use SHARED memory, and as such, the speed of accessing the data is the same (or virtually?) regardless of it's 'LOCATION' or if it's on the STACK or the HEAP (for instance variables as opposed to STATC variables).


Can someone PLEASE clear this up for me? As part of me keeps wanting to put all of these 'array's' into the objects 'init' method and have them as object variables and not static class ones...

Thanks for taking the time to read this really long (and probably confusing and badly written post).
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #2
Elphaba Wrote:a huge order of magnitude slower

How huge is huge? It might not make an actual difference in practice. All theory aside, the only way you can actually be sure is to measure the relative performance between the two approaches. It could well be that storing a large amount of data on the stack every time the function is called rather than storing it on the heap once and just retrieving it each time is actually slower.
Quote this message in a reply
Member
Posts: 227
Joined: 2008.08
Post: #3
Elphaba Wrote:Can someone PLEASE clear this up for me? As part of me keeps wanting to put all of these 'array's' into the objects 'init' method and have them as object variables and not static class ones...

Well ultimately that is a better solution, people will use statically declared model data arrays within a function mainly for the sake of a tutorial.
Doesn't mean you have to do it that way Wink

I have to say though, that was a long post Grin
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #4
I don't think static variables are not stored on the heap, they are stored in statically allocated memory that is loaded when the program is started. Though it doesn't really make a difference if the memory is not cached, the effect is the same.

I'm not sure how true this holds in general, but reading memory is fast if it is cached, but writing to memory will always be slower. That is why you generally optimize code so that you are reading arrays linearly despite whatever order it will be written back in. Vertex Arrays on the other hand generally hold large amounts static data, and not data that you read from the CPU. Also, initializing a large array on the stack takes a lot of time too. It would either have to be built from code, or copied from somewhere not on the stack anyway.

When building vertex data I use static arrays for static data and local arrays for geometry that is built procedurally.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
⌘-R in Chief
Posts: 1,260
Joined: 2002.05
Post: #5
Elphaba Wrote:1. Static declared variables (regardless of them being instance or local to a method) are stored on the HEAP. Non static are stored on the STACK.

Unless it's a local variable it's not going to be on the stack. Instance variables would be in memory too, so unless you're declaring a logically local variable as static inside the method (which would be pointless), then I don't see what the fuss is about.
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #6
All global variables and static local variables are stored in the data section, not the heap. This is the same section of memory as the executable code is stored in.

If I'm correct in my understanding, the decision is between storing the variable as a local static variable vs. a member variable. For accessing, there's a few things to consider. If it's stored as a member variable, it can indeed be brought into the cache along with other member variables of that class due to its memory locality. If it's a static local variable, on the other hand, it has no locality with that class. However, if you call that function often, then the variable may end up being cached better due to the fact that it'll always be grabbing the variable from the same location in memory rather than grabbing a different copy based on the object you passed in if it's a member variable.

Micro-optimizing based on the cache is always problematic because as soon as you get something faster with one processor's cache, it may end up being slower with a different processor's cache. In this day in age, it's something you shouldn't really worry about. Unless something really funky is going on, I very highly doubt that there will be a measurable difference for something like changing a variable from a member variable to a static one or vice versa. If you want to optimize, there are undoubtedly larger issues you can find.
Quote this message in a reply
Member
Posts: 48
Joined: 2009.05
Post: #7
Thank you AKB825 - I think you really understood my point.

Okay, I understand what your saying - perhaps my problem is that alot of the C++ content we were taught this year was in particular relevance to Xbox 360 and PS3 dev - where cache misses are VITALLY important, as are fetching data from anything other than L1 cache.

I was extrapolating that issue to the iPhone because of it's relatively low power.

I should also point out that from a coding layout / style standpoint, having big heaping static vertex arrays in a method just gives me the wiggin's...
Quote this message in a reply
Moderator
Posts: 1,140
Joined: 2005.07
Post: #8
For the impact this will have in performance, I suppose it depends a lot on the situation and where it's being called. For these systems you can do a lot to try to optimize for cache performance, such as making sure you lay out as much in contiguous memory as possible rather than having a bunch of pointers that hop around etc. (like using arrays instead of linked lists, implementing trees using arrays etc.) You can also rearrange data, such as vertices in your vertex buffer, so that you try to group accesses together as much as possible. A lot of those optimizations are easy to see why they improve cache efficiency, and you can point to them with confidence and say "yes, this will be faster."

Changing between a member variable and static variable isn't obvious. As I pointed out before, a member variable can be pulled into the cache with other member variables (assuming the structure is small enough), while at the same time a static variable will stay in the cache when calling the same function multiple times. Both solutions have some sort of cache coherency, and it's not obvious which will be better at which time. This isn't something you can look at and say "this will always be better in all situations." Which will be better depends on many factors such as how many times and how often the function is called and how many different objects it's called with. Furthermore, the performance difference between both methods will be very small compared to a more obvious example, such as a linked list vs. an array, since a linked list has little cache coherency vs. an array which will have good coherency.

This is even before looking at how often the function in question is called. If this is a function that's at the core of many of your performance-critical routines, then it any potential improvement may be worth looking at. If it's not called very often, then oftentimes even obvious optimizations will have a negligible real-world impact to your speed. When dealing with trade-offs like this, where it's not obvious which one will be better, and when it looks likely the "better" one won't even have much of an impact, it'll be more worth while focus your time on something else.

Have you been using any profiling tools? If not, you really should so you can focus your optimizations on bottleneck functions. Otherwise you'll waste a lot of time optimizing routines that give you a very small increase in performance. You're never going to get everything as fast as possible with the most efficient management memory, CPU, GPU, etc., so you might as well just focus on the most important. Otherwise you'll go crazy before too long. Wacko
Quote this message in a reply
Member
Posts: 26
Joined: 2008.08
Post: #9
akb825 Wrote:Otherwise you'll waste a lot of time optimizing routines that give you a very small increase in performance. You're never going to get everything as fast as possible with the most efficient management memory, CPU, GPU, etc., so you might as well just focus on the most important. Otherwise you'll go crazy before too long. Wacko

If only someone had told me that all those years ago when I first started programming! Too late now Wacko
Quote this message in a reply
Moderator
Posts: 3,577
Joined: 2003.06
Post: #10
akb825 Wrote:You can also rearrange data, such as vertices in your vertex buffer, so that you try to group accesses together as much as possible.
BTW, I've mentioned this before, but the oolong engine has a really nice triangle strip orderer. According to the PVR docs the cache locality of the data improves performance, although in practice I can't say I've seen any improvement, so YMMV.

I also use arrays, in general, whenever possible.

The TouchFighter sample uses huge static arrays in its rendering methods. To be more specific, here's like something you'd see:

Code:
void renderSomthing()
{
    static GLfloat VertexData[] = {
        11.2354f, 3.68266f, -2.40073f,
        ...
        };
    ...
    glDrawElements(GL_TRIANGLE_STRIP, 8, GL_UNSIGNED_SHORT, &Indices[60]);
}

It looks like crap to have all that data in the method IMHO, and I don't see how it'd help, since like you said, that's not going to be local since it's "static", and will instead be treated the same as a global (right? i.e. It should be stored in the data section).
Quote this message in a reply
Member
Posts: 48
Joined: 2009.05
Post: #11
Exactly 'Jake. That's why the static thing has me confused about 'good coding practice' and 'efficiency'

Even though Apple seem to have done this in 3 of their OpenGL demo apps ( TouchFigher, Crash Landings and the template itself ) I just can't help to think they did it for 'laziness' and not for a 'proper' reason.

:/

There have been a lot of interesting points made on this thread so far, so I'm glad it wasn't a totally ******** question to ask and that others seem to be getting something from it too.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Adding lots of static shapes in Chipmunk - performance question TomorrowPlusX 3 7,427 Jul 11, 2011 01:39 PM
Last Post: Skorche
  Chipmunk Static Friction Piazzolla 0 2,666 Jul 21, 2009 11:06 AM
Last Post: Piazzolla
  Adding static gravity object game_ding 4 4,907 Mar 28, 2008 05:25 PM
Last Post: Skorche