Acknowledged

ByteArray addAll() not Memory Efficient

When using the addAll() method of Lang.ByteArray, peak memory usage implies that the ConnectIQ framework is doubling the size of the array being appended to instead of extending it by the size of the appended array.

For example, let's say we create a 1K byteArray called myArray and run the following code starting with an empty byte array, longByteArray:

while(longByteArray.size() < 32768) {
    longByteArray.addAll(myArray);
}

An efficient implementation would grow peak memory usage by ~1K more than longByteArray.size(). Instead, we see peak memory usage growing with longByteArray.size() * 2 + 1024.

It may also be worth noting that the Monkey C extension for Visual Studio code will time out as the array grows if a developer sets a breakpoint on the addAll function above while the watch window is open to longByteArray.

Parents
  • Memory has always been tight in CIQ,  I can't see a way this could change.

    By "timeout", you mean the watchdog?  That's how long something can run without returning to the VM,  You can work around this by using a time and do part of the copy during each timer tick.

Comment
  • Memory has always been tight in CIQ,  I can't see a way this could change.

    By "timeout", you mean the watchdog?  That's how long something can run without returning to the VM,  You can work around this by using a time and do part of the copy during each timer tick.

Children
  • I'm not sure I follow. If I preallocate an 8K array and rubber stamp a 1K array 8 times, the peak memory usage looks fine:

    for(var j = 0; j < 8; j++) {
        for(var i = 0; i < 1024; i++) {
            longByteArray[(j << 10) + i] = myArray[i];
        }
    }

    The exact sizes here (8K vs. 32K) don't really matter - the point is that CIQ could provide a native function for assigning blocks to a preallocated array without using more memory than is necessary. The above loop proves that it is possible to do this in VM code (running this in the simulator I see peak memory usage about 1K above total memory usage), so it should be possible for CIQ to the same in native code.

  • If you are doing an add() or addAll() the original array only has enough memory allocated for the original array.  That's why it needs to allocate memory for the new (larger) array.

    By the way, what will you being with this 32k ByteArray?  You can't save it to storage or send it using comm...

  • I feel like the native CIQ addAll() function could detect that there is enough memory preallocated in the target array to add bytes without allocating temporary memory.

    Correct, I mean the watchdog. I understand that it's possible to split the operation to avoid a watchdog timeout, but this seems like it would represent a workaround on top of a workaround for addAll(). Using a loop to add the bytes is also a lot less time efficient than addAll() since it has the advantage of native code.