DS Grid vs 2d Array: Speed and 4 other Questions

1. Which is faster a DS grid or 2d array?
2. Which are local or global?
3. Which need to be destroyed before destroying the object that made them, to free up memory?
4. Which are persistent/nonpersistent?
5. Which take more memory?
 

Bayesian

Member
You can answer all these questions yourself

1. Test with code
Code:
var timeStart = get_timer();

//complex or looped operation

var timeEnd = get_timer();
var time= timeEnd - timeStart;
show_message(time)
Run this for an array operation and then a mirror ds_grid operation and compare

You'll see that ds_grids are usually much faster

2. Read the documentation.
https://docs.yoyogames.com/source/d...uage overview/variables/global variables.html
Just like local variables, global variables must be declared
Code:
myLocalArray = []
myLocalGrid = ds_grid_create(0,0)

global.myGlobalArray = []
global.myGlobalGrid = ds_grid_create(0,0)
4.
https://docs.yoyogames.com/source/d...instances/instance properties/persistent.html
Persistence is an instance variable

3 and 5.Create a simple game

objGame creates and destroys objArray and objGrid with key board keys

objArray has a very large array
objGrid has a very large ds_grid

Run the debugger and:

for 3
create a few of one type of object
observe the memory increasing in the profiler
then destroy them all
observe whether the memory goes back down
repeat for the other type

You'll see that GM doesn't garbage collect for either of them

for 5
in a fresh room observe how much memory n objects of one type take
refresh the room and repeat for the other type with the same n of objects

You'll see there's basically no difference
 

FrostyCat

Member
1. Test with code
Code:
var timeStart = get_timer();

//complex or looped operation

var timeEnd = get_timer();
var time= timeEnd - timeStart;
show_message(time)
Run this for an array operation and then a mirror ds_grid operation and compare

You'll see that ds_grids are usually much faster
This is only the case for batch operations like setting/adding an area, where the loop is faster when executed at the runner level instead of at the GML level (which has additional type-handling baggage). For single-entry access, I have never noticed a tangible difference except for when people fail to clean after them.
3 and 5.Create a simple game

objGame creates and destroys objArray and objGrid with key board keys

objArray has a very large array
objGrid has a very large ds_grid

Run the debugger and:

for 3
create a few of one type of object
observe the memory increasing in the profiler
then destroy them all
observe whether the memory goes back down
repeat for the other type

You'll see that GM doesn't garbage collect for either of them
This is a common fallacy that a lot of GM users have about freeing memory. When things get GC'ed (as is the case for strings and arrays) or manually freed (as is the case for data structures, buffers and the like), the memory goes back into a pool managed by the runner, not directly back into the heap. You will NOT see an immediate change in Task Manager until the pool decides to give some of it back.

Arrays can and do get GC'ed if there are no remaining references to them. Data structures need manual cleanups.
 

TheouAegis

Member
General rule of thumb: If you need to create a resource or data structure using a function with the word "create" or "add" in it (ignore the array_create function, because you don't need it), then that resource or data structure will be globally persistent and will need to be manually destroyed or freed before removing the reference to it or recreating it.
 

Bayesian

Member
Run the memory management test every step for 10 to 30 seconds.
Perfect, I see now
Code:
instance_create_layer(0,0,layer,oArray)
instance_destroy(oArray)
With that in step my memory barely fluctuates
Code:
instance_create_layer(0,0,layer,oGrid)
instance_destroy(oGrid)
But this creates a memory leak

Why doesn't my original test work?
 

FrostyCat

Member
Why doesn't my original test work?
Your original test failed because you only created the test object instances once. The memory will always go up the first try, since the memory pool needs to be expanded to accommodate the new array or grid. It's the subsequent tries in the same run that would reveal the difference.

When the instance of the array testing object is destroyed, the array's space gets returned to the runner's pool by the GC. When you create another instance of it afterwards, the array doesn't initialize off new memory that the runner requests from the heap, it initializes off existing memory that used to belong to the destroyed instance's array. That's why in your correct test, the memory usage stays almost constant.

When the instance of the grid testing object is destroyed, the grid's space won't return to the runner's pool unless you run ds_grid_destroy() (which you would obviously leave out here because you want to test for GC behaviour). When you create another instance afterwards, the grid can't initialize over the destroyed instance's grid because it still exists. Instead it has to get the runner to ask for more from the heap, add that to the pool and initialize over the new space. That's why in your correct test, you get a leak this way.
 

Bayesian

Member
Your original test failed because you only created the test object instances once.
I was creating 10 then deleting all of them them then creating 10 more when I tested this

I realized the reason my original test wasn't working was because I wasn't actually deleting any objects because of the way I set up the project.
 
Top