I’ve got a question about how allocation works for plugins. Correct me if I’m wrong but since plugins are instantiated with “new”, they are all on the heap to start, but, after testing, it seems that there seems to be to some cache locality benefit to using C-style arrays or other stack-based members (of AudioProcessor) even though it is on the heap already.
Does the executable code section (member functions) live in the same address space of the member data?
Is your question related to where the plugin binary is loaded in memory or how instances of that plugin are managed? Anyway the functions called in your plugin are proceeded exactly as the functions of the host. By the way note that i’m not an expert in VST and such.
A member is allocated inside its owner. It may happen to contain a pointer to some memory out of itself, and then out of its owner, allocated with new. A member is not on the stack or the heap by itself: it is wherever its owner happens to be.
If you create an object with a C-style array or std::array member in a local variable, it’s on the stack, with the array inside of it.
If you create the object with new, it’s on the heap, with the array also inside of it.
If you create an object with an std::vector member in a local variable, it’s on the stack, with the std::vector inside of it, but the std::vector contains a pointer to the actual data on the heap.
If you create the object with new, it’s on the heap, with the std::vector inside of it, but the std::vector contains a pointer to the actual data in some other place on the heap.
Even if the whole thing is created on the heap, a member that’s fully contained by its owner may benefit locality. It also may not: if it’s a large block, and the stuff before and after happen to be used together in a time critical section, it can make things worse. As a rule of thumb, I tend to put buffers and other large blocks on the heap, but small arrays / structures as fully contained members, especially if they’re used in conjunction with other members in time critical sections.
Thanks for the addition. I had not check so far but from cppreference.com it seems you are correct:
If an optional<T>contains a value , the value is guaranteed to be allocated as part of the optional object footprint, i.e. no dynamic memory allocation ever takes place. Thus, an optional object models an object, not a pointer, even though operator*() and operator->() are defined.