# Tips


## Memory Allocations

The MetaModule has hard real-time requirements in order to acheive low-latency
audio. 

There is an audio "thread" which has the highest priority of any task. The
audio thread calls your module's `process()` or `update()` function for each sample frame.
Therefore any code in the `process()` function must be optimized for efficient
execution.
 
This means you cannot make any memory allocations in the `process()` function
(or any other function that's called by `process()`. This includes:

- Do not create, destroy, or re-size a `std::string`. Writing characters to an
  already allocated string is OK, as long as it does not change length.

- Do not `push_back` or `emplace_back` or otherwise change the length of a
  std::vector (or any std container such as list, deque, etc...) You can
  read/write data in a vector, but don't change the capacity of the vector. If
  you do need a dynamically-sized vector in the audio thread, one useful
  technique is to use `reserve()` when you construct your module. Then you can
  safely call `push_back` in the audio thread as long as you are 100% certain
  you will not push more items than you reserved.


I've seen a few examples of VCV Rack plugins that allocate memory in the audio
thread. The most common example is allocating channels when a cable is patched
into a jack. Often, the number of polyphonic channels is read from the port and
then a vector of some data structure is allocated to accomodate that many poly
channels. This is not allowed in the MetaModule. I suspect it's OK in VCV Rack
because typically Rack is run on modern computers which can handle spikes in
CPU usage coming from allocations. But the MetaModule will behave erratically,
sometimes doing OK and sometimes failing when you patch a cable.

In order to address this pattern in several VCV Rack modules, the MetaModule
runs `process` once for each module when it first loads the patch. Sometimes
modules will allocate only if they detect their data structures have not been
set up.

If you are designing a new module, I would put forth a suggestion to set up all
data structures in the module constructor. That includes anything that requires
a heap allocation. Use `reserve()` if you still need dynamic re-sizing.

Then, in the `process()` function, make sure there is no situation in which a
memory allocation can happen.

## Memory

The MetaModule has about 300MB of RAM dedicated for plugins to use. This includes
the plugin code (but not data such as PNG files), and any memory individual modules
in the patch will use. Be mindful that this is a shared resource, so try to 
keep the memory footprint low if your module deals with large buffers (several MB or more)
or is able to load files of arbitrary sizes. Remember that users will often want
duplicates of a module in a patch to make it 4-voice, 8-voice, etc. 

## Disk Access

File system access is permitted on the MetaModule. However, it is much slower than
on a desktop computer. Also keep in mind that file paths differ on the computer
than they do on the MetaModule.
Use the helper function `translate_path_to_local()` to convert a computer
path to a MetaModule path (see [Filesystem Calls](./filesystem-syscalls.md)


## Block sizes

The minimum block size the MetaModule supports is 16 frames. So if you are
optimizing your module to process in blocks, this would be the ideal size to
use. 

Using a larger size would mean the CPU usage would spike, which can be
upsetting and confusing to users.

## UnInitialized data

Make sure any variables you use are initialized to a valid value. I do not
have hard data to back this up, but my experience has been that often a desktop
OS will return zero-intialized memory when you request an allocation.
Perhaps this is a security feature? In any case, the MetaModule does not do this
(and good coding practices tell us to always initialized a variable before reading it).

Bugs that result from using uninitialized data might not show themselves until
you port to the MetaModule.

For example:

```c++
class MyModule : rack::Module {
    float increment;

    void process() {
        int index = std::floor(increment);
        float output = wavetable[index];


```

Clearly, if `increment` is some value greater than the size of the wavetable,
the module might crash. On desktop system, you are more likely to get a value
of 0 for `increment`, therefore the bug will not show itself.

## MetaModule platform vs. Computer (VCV Rack) platform

The MetaModule runs without an operating system, and so has some different
requirements than code written to be run on a desktop computer for VCV Rack.
Also, subtle bugs or or less-than-ideal practices might rarely cause a problem
on a fast computer with GB of RAM, but might cause frequent issues with the
MetaModule's constrained resources. So, the process of porting can bring to
light these issue.

