• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

v1.4.1757 : broken ds_grid_get is game breaking!

Ronchon

Member
After updating from v 1.4.1657, i've been experiencing game freezes.
In places where my game didn't freeze at all, it now freezes for more than 30 seconds!!

After diagnosing, turns out the ds_grid_get function itself seems to be more than 30 times slower than in the previous version, causing this 30 sec freeze for something that used to barely take a second before...

Of course, as usual, impossible to downgrade as there's always problems with gamemaker when downgrading.
Seems that licensing is now simply broken in v 1.4.1657 as i'm unable to properly activate GM and get a licensing request at every start ( and yes i tried multiple times to uninstall everything and delete all appdata folders etc.. ).

So i'm apparently stuck with this version that has broken ds_grids.
Here is a quick test to confirm the ds_grid_get were abnormally slow, though i can't actually test it with previous version and prove the difference.


n = 0
t_start = current_time
g = ds_grid_create(140,280)
for(sc_y=1;sc_y<140;sc_y+=1)
{
for(sc_x=1;sc_x<280;sc_x+=1)
{
val = ds_grid_get(g,sc_x,sc_y)
n+=1
}
}
show_message("test time = "+string(current_time-t_start)+" nb "+string(n) )

On my machine this test outputs 1280ms, for about 38000 ds_grid_get .
In previous versions this was pretty much instantaneous and causing no significant freeze.

If someone still uses v 1.4.1657 i'd be interested if they could run this code and give the time they get ( though obviously it also depends of the PC spec ), as i'm unable to revert back and get the exact value.


EDIT:
I ran more tests and it gets even weirder.


//test 1 ( ds_grid_get with constant coordinates ): result < 10ms
n = 0
t_start = current_time
g = ds_grid_create(140,280)
for(sc_y=1;sc_y<140;sc_y+=1)
{
for(sc_x=1;sc_x<280;sc_x+=1)
{
val = ds_grid_get(g,10,10)
n+=1
}
}
show_message("test 1 time = "+string(current_time-t_start)+" nb "+string(n) )


// test 2 ( using ds_grid_get without 'for' ): result <10 ms
n = 38000
t_start = current_time
g = ds_grid_create(140,280)
repeat(n){ds_grid_get(g,10,10)}
show_message("test 2 time = "+string(current_time-t_start)+" nb "+string(n) )


//test 3 ( using 'for' without ds_grid_get ): result < 10 ms
n = 0
t_start = current_time
g = ds_grid_create(140,280)
for(sc_y=1;sc_y<140;sc_y+=1)
{
for(sc_x=1;sc_x<280;sc_x+=1)
{
n+=1
}
}
show_message("test 3 time = "+string(current_time-t_start)+" nb "+string(n) )


//test 4 ( ds_grid_get with random coordinates independent from " for " statement ): result < 20 ms
n = 0
t_start = current_time
g = ds_grid_create(140,280)
for(sc_y=1;sc_y<140;sc_y+=1)
{
for(sc_x=1;sc_x<280;sc_x+=1)
{
ds_grid_get(g,irandom(100),irandom(100))
n+=1
}
}
show_message("test 3 time = "+string(current_time-t_start)+" nb "+string(n) )




Test 1, 2, 3 and 4 output results below 20ms. Which is pretty much the expected amount of time these kinds of operations used to take on my machine.

As we can conlude with the test 1 to 4, weirdly, it seems to have to do with ds_grid_get using variables of the 'for' statements or something...
Anyway there's definitly something broken here, and the difference is so huge it simply makes my game out of order.
I need a fix urgently considering i couldnt downgrade!
 
Last edited:
I

icuurd12b42

Guest
You reversed the x and y for col and row

the moment your grid access is out of bounds you get slowness. I'm surprised you did not see the console output...


Grid 0, index out of bounds writing [268,139] - size is [140,280]
Grid 0, index out of bounds writing [269,139] - size is [140,280]
Grid 0, index out of bounds writing [270,139] - size is [140,280]
Grid 0, index out of bounds writing [271,139] - size is [140,280]
Grid 0, index out of bounds writing [272,139] - size is [140,280]
Grid 0, index out of bounds writing [273,139] - size is [140,280]
Grid 0, index out of bounds writing [274,139] - size is [140,280]
Grid 0, index out of bounds writing [275,139] - size is [140,280]
Grid 0, index out of bounds writing [276,139] - size is [140,280]
Grid 0, index out of bounds writing [277,139] - size is [140,280]
Grid 0, index out of bounds writing [278,139] - size is [140,280]
Grid 0, index out of bounds writing [279,139] - size is [140,280]
....
 
I

icuurd12b42

Guest
revised code. 17 nb

n = 0
t_start = current_time
g = ds_grid_create(140,280)
for(sc_x=1;sc_x<140;sc_x+=1)
{
for(sc_y=1;sc_y<280;sc_y+=1)
{
val = ds_grid_get(g,sc_x,sc_y)
n+=1
}
}
show_message("test time = "+string(current_time-t_start)+" nb "+string(n) );
 

Ronchon

Member
Damnit! How could i miss that ><
Well i guess that's why i needed someone to check these results ^^ Thanks!


However that still doesnt explain why my game completely freezes taking 30 sec to do something that was instantaneous in the previous 1657 version...
Back to square one, i'll make other tests to try find out what's going on!
 
I

icuurd12b42

Guest
pin point it. Maybe you old code is accessing stuff out of bounds too...
 

Ronchon

Member
Yes apparently it is related to accessing stuff out of bounds.

For some things, it's a convenient thing to be able to do that, though it would be too long and useless for me to explain in what cases i'm using this for my game.
I need that to save some memory. To explain approximately , it's because i have general mechanisms that can receive different kinds of grids as input. If i had to make sure all the grids have the correct size for the mechanism, i'd have to resize lots of grids uselessly big and waste lots of memory.
The thing is , it was never an issue before. So it would seem in the new version, accessing stuff out of bounds is now a hundred times slower than before ?
That's quite a problem for me :(

I tried doing this , doing the check myself, and its still incredibly faster than letting ds_grid_get do the bound check by itself in this new version...
if ds_grid_width(g)>300 && ds_grid_height(g)>300 then val = ds_grid_get(g,300,300)

So i'm going to encapsulate ds_grid_get into my own function to avoid these problems.

I still think it's not normal for ds_grid_get to be THIS slower when accessing out of bounds values. Especially considering how doing the check yourself in GML is incredibly faster.
 
Last edited:
I

icuurd12b42

Guest
Your are going to have to set limits of your iterators to the max size of the grid. Simply put, you cant be lazy anymore with these and also in the old days accessing an out of range position would result in getting/setting the edge cells which could be a problem in an error inducing sort of way...
 

Ronchon

Member
But that's the thing , it's not "lazy " to access out of bounds values. Its a usefull behavior that allows certain things that cannot be done without it.
Anyway as i stated, i'm encapsulating it to preserve that behavior.
As for the error inducing, i'm used to keep ds_grid bounds in mind when i need it i have had no major problems with it.
 
I

icuurd12b42

Guest
Yes, the term lazy... so you can't be lazy and rely on it to work like that, you should have your own clamping to stay in range, in fact you probably should always have had that code, the edge return behaviour if I recall was never documented. the way it was implemented before allowed for lazy programming, it allowed users to be careless in accessing the cells, and more often than none people would go out of bound never intending to... with grids and lists and other structure.

I also rely on clamping along the border in some instances and I too had had to change my code. But this new behavior also exposed a few places where I was going out of bounds and ultimately fixed other weird issues.

They changed a lot of stuff that will expose lazy programming when they added undefined as a possible return also so be aware of that.
 
Top