Free an array

Monkey Forums/Monkey Beginners/Free an array

hub(Posted 2015) [#1]
Hi !
Is there a way to quickly free and array ?
Thanks.


dawlane(Posted 2015) [#2]
Well I would have thought that setting the array to MyArray=NULL would do the trick and let the GC clean it up when it gets round to it. But GC doesn't work the same on all targets.

See http://www.monkey-x.com/docs/html/Programming_App%20config%20settings.html
for GC settings.


MikeHart(Posted 2015) [#3]
use

yourArray = yourArray.Resize(0)



MikeHart(Posted 2015) [#4]
Ok, that doesn't free it actually. Better read completely before I write. Sorry.


hub(Posted 2015) [#5]
target = android.


dawlane(Posted 2015) [#6]
As you are targeting Android. I would suggest looking array reuse rather than trying to free the whole array. I would think that suitable classes that should not be too much of a performance hit for this would be Pool and Stack.


hub(Posted 2015) [#7]
it's just when i want reload all my data without quit and lauch the app So perhaps resize(0) is in my case a good choice ?


ImmutableOctet(SKNG)(Posted 2015) [#8]
This should cover most of the pitfalls, and behaviors you'll encounter with arrays:

The formal syntax to empty an array is []. 'Resize' should work just as well. If you need direct control over a block of memory, and its perceivable storage, use 'DataBuffer'. As stated, for dynamically sized arrays, 'Stack', 'Pool', and 'Deque' objects are ideal, unless you intend to roll your own container or storage system. As brought up, large arrays are heavy, just as 'DataBuffers' are, but they can be larger than needed (In the case of storing bytes as an integer array; use 'DataBuffer' here).

The problem with "freeing" an array in Monkey is that there's no rules regarding "views" of them. With this in mind, a manual discard (If possible) would be dangerous (Like 'DataBuffer.Discard', only less obvious). As a side note, this is also why array slicing can be costly on some targets.

Just to clarify one point about 'Resize', and why it may be confusing: Because of Monkey's behavior with arrays, calling 'Resize' is the same as creating a copy of the array you use it on. The only difference from the original array is its place in memory under the hood, and the number of elements you request. This isn't a "view slice" of any kind, it's a clone. So, when you call 'Resize(0)', you're asking for a clone of your original array, only with zero elements (Blank). In other words: This does not in any way modify the original array, so you need to assign your field/local/whatever to the resized (In the case of 0, blank) array.

This is why I suggest using '[]', as you can write:


Now, it should be brought up that an array in Monkey is considered "never 'Null'". That is, they're like 'Strings'; they aren't native or externally declared objects, they're language constructs. Arrays are always safe to use, but their contents are dependent on how you use them; like 'Strings'. So, use of 'Length' on an array or string is always safe, even if it's empty or otherwise considered uninitialized. As a side note, arrays are not comparable like 'Strings' are; you'll need to write your own deep-compare routine.

With that in mind, however, what is your intention by doing this? If it's about cleaning up an object that you'll no longer use, then don't do anything. Arrays are reference-counted like every other object, they just have special properties. If you want to release the array, don't do anything. As long as you aren't referencing it, or referencing something that's referencing it (Recursive), it'll be taken care of by the garbage collector. This means if you have an object that holds a reference to say, an 'Int[]', and you no longer reference that object, that integer array will be taken care of automatically. (Obviously this applies to other types of arrays)

But, when your intention is to reset, or to otherwise pool an object that uses an array, this complicates things. It all depends on your setup. For example, you could use a system that allocates fixed-size arrays that pooled objects can reference. It's also possible for you to implicitly attach the storage of an array; like when using 'Int[256]' as your field's type, or initially using 'New Int[256]' when constructing the object, but not assigning to '[]' (Or using 'Resize' and assigning the array) when you reset the object for pooling. In such a case, you could treat the content of your array as initially undefined (e.g. potentially non-zero), or you could reset the contents with a loop or function. In the case of object arrays, you're dealing with an array of references to objects, so this gets a lot more dangerous. Because an array of type 'T' (Where 'T' is an object) is telling the compiler to allocate references, keeping the contents non-Null is very bad practice. So, in those situations, assign each element (Reference) to 'Null' when "destructing" and/or pooling the object. This also applies to "broker" systems like I mentioned before.

There, that should be just about everything you need to know about arrays and their storage. I hope this helps.


hub(Posted 2015) [#9]
Very interesting skng ! Many thanks !


ziggy(Posted 2015) [#10]
So, in those situations, assign each element (Reference) to 'Null' when "destructing" and/or pooling the object.
You can also reset references by just assigning to a new array of same size, so no need to iterate nulling each element. In fact, if the array is not referenced any more, array references are also collected properly.

Take into account that Monkey does not use Ref counting GC. It uses a proper GC on C++ and handle cycles on all targets.


ImmutableOctet(SKNG)(Posted 2015) [#11]
@ziggy: I already went over array reference-semantics in my post, and doing what you're suggesting is horribly costly for large arrays. For example, an array of 1024 references takes up an entire page on x86, and most x64 systems. From what I've read, this is the same with ARM as well. Now, if we consider Microsoft's track record with Windows (Especially on my system), this isn't a meaningless allocation.

As for reference counting, I wasn't referring to implementation details, I was referring to the concept. Whether the GC uses recursive "tracing" (Mark/sweep, etc), that isn't relevant when you already understand that an unreferenced object is released. Either way, I suppose it is better to be more verbose, so I agree with the sentiment.


Shinkiro1(Posted 2015) [#12]
> it's just when i want reload all my data without quit and lauch

then there is no need to resize the array at all.
just overwrite the values in the array.

as mentioned above, the old objects will be taken care of automatically by the gc.


Steve Ancell(Posted 2015) [#13]
myArray = [] works too.


ziggy(Posted 2015) [#14]
As for reference counting, I wasn't referring to implementation details, I was referring to the concept. Whether the GC uses recursive "tracing" (Mark/sweep, etc), that isn't relevant when you already understand that an unreferenced object is released.
I see, but ref counting is an implementation detail! :) I suppose you meant a garbage collector in an abstract sense. Mark/Sweep is not a kind of ref counting GC. Ref counting does not handle ref cycles and is very problematic and slower than most proper GC implementations. For this reasons, I considered it was worth mentioning that Monkey does not use any Ref counting based GC. AFAIK, It uses mark&Sweep in C++, but tied to the "after On whatever" method, and generational (which is better) in other targets.
You can also enable other GC modes on C++, but I think they're all still non generational (not sure, I think it was like this last time I looked at it).

I already went over array reference-semantics in my post, and doing what you're suggesting is horribly costly for large arrays.
Yes, my post was not the best post in the world. What I really meant to say is that you do not need to free an array. If you need a new array of the same size with null elements, you can create it directly. (I've found this to be a lot faster in JavaScript than nulling all elements!)

Anyway, most of the time, you won't need to free an array. If you need to discard array contents because it contains unmanaged memory elements that need to be discarded (such as images loaded into VRam), then you need to Clear each element, but the array only needs to be dimmed to [] as ImmutableOctet(SKNG) wisely says, or just ensure the array itself gets out of scope.