Does it matter if a variable is declared in process()?

When I’m programming a module, I’ll declare variables in the module struct if I need those variables to persist over subsequent calls of process(). If I don’t need persistence I’ll just declare variables inside process().

My question is, does this have any appreciable effect on performance? Is continually declaring (and presumably destroying?) variables within the process() function call any different to declaring those functions once per module?

If they are simple variables like ints or floats, there won’t be any meaningful affect on performance.

If they are actual more complicated objects, it depends on what constructing and destroying those objects entails.

2 Likes

Yes, what @Xenakios says is correct. We all do that. making a new stack frame with new local variables is super efficient with modern processors and compilers. I wouldn’t worry about it. In fact, I wouldn’t be at all surprised if the compiler makes a new stack frame anyway, even with no local variables. But for sure it’s a good practice to use local variables.

2 Likes

I would actually assume using class member variables needlessly will be slower because those might not be in the CPU cache as readily as stack local variables. (But of course if a variable has to persist between the process() calls, there’s no way to avoid using the class member variables.)

1 Like

Declaring a process() local as a static would get the compiler to persist it in the most efficient way possible. It would likely be a hidden class member.

NEVER do that, multiple instances of the module will break if you use static variables. And static variables are very inefficient anyway.

You’re thinking static static if such a construct were possible? The outer context would be the struct not global.

No, I mean static variables declared locally for example in the process() function.

void process(const ProcessArgs& args) override
{
  static int x = 0; 
  ++x;
}

That would be hopelessly broken code, all the module instances running in Rack would be using the same variable, potentially from multiple threads. (The same of course applies for global/static variables declared elsewhere too, they should almost never be used.)

Our experience with the Faust compiler is that local (= stack allocated) variables are faster to use than fields in the structure.

1 Like

That makes sense for simple types as the stack relative load/store would likely be faster than having to index relative to a base pointer obtained from the stack?

Yep c++ - Static variables in member functions - Stack Overflow seems it does get bumped up the scope to a hidden in function only available global.

Just want to beat this dead horse. It has happened time and again that someone new to C++ uses a static or a global because they want a variable to persist between process calls. Then the bugs come in with multiple instances.

So, to reiterate, you should never, ever make a static or a global unless you are really sure that’s what you want, and you are very sure that you have considered all the threading implications. You probably want a member variable in your module class.

3 Likes

People do the darndest things. At the processor level, the “this” pointer is in a register & the member offset is small enough to code it in the fetch instruction. So it’s two machine instructions to access a member in most cases.