At the moment I’m working with some large data sets, and if I’m not careful, end up crashing sclang with the following message returned to the post window:
Interpreter has crashed or stopped forcefully. [Exit code: 11]
Some example code:
~testSize = 2.pow(25).asInteger // works fine
~testSize = 2.pow(27).asInteger // Array FAILS here (64bit ints?) <--
~testSize = 2.pow(29).asInteger // FloatArray FAILS here (32bit ints?) <--
~testArray = Array.newClear(~testSize)
~testArray = FloatArray.newClear(~testSize)
My system is:
SuperCollider 3.13.0-rc1
MacOS 13.0.1.
Physical Memory: 128.0 GB
Is there an easy way to find out the maximum sizes available for the various Collection subclasses? (E.g., max size supported for Array, List, FloatArray, etc.)
Also, is this limit fixed with the SC compile? (Presumably, yes?)
RawArrays are more like C arrays – you know in advance the data type of every element, so you can predict the memory size based on the size of the data type times the number of elements.
FloatArray is for single precision floats, so the storage size will be 4 * array_size. (For a raw array of double precision floats, use DoubleArray.) It’s suggestive, though not conclusive of anything, that 4 * (2 ** 29) == (2 ** 31).
Array is an array of “slots” – basically pointers to SC objects. This is how Array can store mixed types, with the side effect that Array requires more storage (because the memory chunk for the array itself is – I think(?) – storing pointers, and the objects require storage on top of that).
Not to my knowledge. I believe (but haven’t checked the source code) that RawArrays just malloc() what they need. But you’re not running out of physical RAM… so I don’t know.
One problem is that in sclang collection sizes are limited to 32 bits - even on 64-bit platforms.
To make things worse: sclang’s memory allocator, while having size_t as the size parameter, internally works with signed 32-bit integers. If you pass a larger size than 2^31 (= 2147483648) it enters “undefined behavior” territory and crashes.
A “slot” in 64-bit sclang takes up 16 bytes (8 bytes for the union + 8 bytes for the type tag and padding). 2^31 / 16 = 134217728. This matches @prko’s empirical limit for Array sizes.
4 bytes for a type tag, then either 64 bits of data or a 64-bit pointer + padding = 16 bytes per slot (and in the case of a pointer, the object needs additional storage, e.g. struct PyrObject* o; has to point somewhere)… posted then saw Spacechild’s correction.