Search code examples
matlaboptimizationbuffercircular-bufferprocessing-efficiency

Circular buffer in MATLAB, **without** copying old data


There are some good posts on here (such as this one) on how to make a circular buffer in MATLAB. However from looking at them, I do not believe they fit my application, because what I am seeking, is a circular buffer solution in MATLAB, that does NOT involve any copying of old data.

To use a simple example, let us say that I am processing 50 samples at a time, and I read in 10 samples each iteration. I would first run through 5 iterations, fill up my buffer, and in the end, process my 50 samples. So my buffer will be

[B1 B2 B3 B4 B5]

, where each 'B' is a block of 10 samples.

Now, I read in the next 10 samples, call them B6. I want my buffer to now look like:

[B2 B3 B4 B5 B6]

The catch is this - I do NOT want to copy the old data, B2, B3, B4, B5 everytime, because it becomes expensive in time. (I have very large data sets).

I am wondering if there is a way to do this without any copying of 'old' data. Thank you.


Solution

  • One way to quickly implement a circular buffer is to use modulus to circle back around to the front. This will slightly modify the order of the data from what you specified but may be faster and equivalent if you simply replace the oldest data with the newest so instead of

    [B2 B3 B4 B5 B6]
    

    You get

    [B6 B2 B3 B4 B5]
    

    By using code like this:

    bufferSize = 5;
    
    data = nan(bufferSize,1)';
    
    for ind = 1:bufferSize+2  
    
        data(mod(ind-1, bufferSize)+1) = ind
    
    end
    

    and this works for arbitrary sized data.

    If you're not familiar with modulo, the mod function returns effectively the remainder of a division operation. So mod(3,5) returns3, mod(6,5) returns 1, mod(7,5) returns 2 and so on until you reach mod(10,5) which equals 0 again. This allows us to 'wrap around' the vector by moving back to the start every time we reach the end. The +1 and -1 in the code is because MATLAB starts its vector indices at 1 rather than 0 so to get the math to work out right you have to remove 1 before doing the mod then add it back in to get the right index. The result is that when you try and write the 6th element to your vector is goes and writes it to the 1st position in the vector.