with() vs dot operator

N

Nabil Kabour

Guest
When addressing a single instance which of these two operators is more efficient? To make it more clear I'll show two pieces of code. So is this more efficient:
Code:
var inst = instance_create_layer(0,0,"Instances",obj_player);
inst.x = 10;
inst.y = 30;
or this:
Code:
var inst = instance_create_layer(0,0,"Instances",obj_player);
with(inst)
{
    x = 10;
    y = 30;
}
Obviously in this example there won't be a noticable difference, but in the larger scale, and just general programming, which is better practice and more efficient? Thanks.
 

Simon Gust

Member
The dot-operator is faster in this case but only because you're only passing 2 variables.
If there are say 100 variables, I am pretty sure, the with statement would be faster.
 
N

Nabil Kabour

Guest
The dot-operator is faster in this case but only because you're only passing 2 variables.
If there are say 100 variables, I am pretty sure, the with statement would be faster.
Cool. Up until how many variables would you say it is better to use the dot operator?
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
On the larger scale, with() is more efficient, as it does not have to do a (numeric ID) -> (actual instance) lookup on each write. If it's <5 variables, the difference is negligible
 

TheouAegis

Member
Also with() inherently verifies each id exists. Dot operator assumes you already verified existences.

Also keep in mind of you are going to need to point back to the calling instance, that throws things off a bit too.
 
N

Nabil Kabour

Guest
Also I don't think this is worth making a new thread for, but does using the dot operator or the with() function greatly affect performance? Should I be using global variables instead? Should I even be worried about these things?
 

Simon Gust

Member
Also I don't think this is worth making a new thread for, but does using the dot operator or the with() function greatly affect performance? Should I be using global variables instead? Should I even be worried about these things?
Yes, they do. Compared to any other variable access method, dot and with are the slowest by far.
example: reading an array from another object
Code:
for (var i = 0; i < array_length_1d(object.array); i++)
{
    var entry = object.array[i];
    // etc
}
In this example code, you are reading the array using the dot-operator every iteration. This is way slow.
What you should do, is either make the array global or make a shortcut once before the loop starts like this
Code:
var arr = object.array;
for (var i = 0; i < array_length_1d(arr); i++)
{
    var entry = arr[i];
    // etc
}
@Wraithious made this little chart some time ago
upload_2018-9-6_23-5-54.png
 
Z

zendraw

Guest
it depends. generally you shuld use with, its optimisation goes further by skipping an instance_exist IF, but there are cases you must use the . like those cases for me are usually when i need to read a temporary variable from the instance becouse they cant be recalled thru the with statement.
 
N

Nabil Kabour

Guest
Yes, they do. Compared to any other variable access method, dot and with are the slowest by far.
example: reading an array from another object
Code:
for (var i = 0; i < array_length_1d(object.array); i++)
{
    var entry = object.array[i];
    // etc
}
In this example code, you are reading the array using the dot-operator every iteration. This is way slow.
What you should do, is either make the array global or make a shortcut once before the loop starts like this
Code:
var arr = object.array;
for (var i = 0; i < array_length_1d(arr); i++)
{
    var entry = arr[i];
    // etc
}
@Wraithious made this little chart some time ago
View attachment 20531
Just out of interest, what do the time intervals stand for in the charts? Obviouslty it's not for one operation (0.2 seconds setting a variable). Yeah I use the shortcut method. It's gotten to the point where im using id.id.var in my game. I don't know if it's bad practice, but using global variables instead is unintuitive.
 

Dupletor

Member
actually: "." will apply to 1 instance only. and if no instance exists the game breaks!!
"." applies to all the instances in which it is valid to be applied to. If it is not logical to apply to many instances, it will be applied to the first in priority order.

If you have a pointer called "instance" pointing to an instance,
Code:
instance.x++;
will apply it to the instance pointed by the pointer.

If however you have an object called "instance", the same code will make all instances of the object move 1 pixel to the right.

However, funnily enough, this is exactly how it works: (Now with the object "obj")

obj.x++ means obj.x =obj.x + 1;
obj.x = obj.x + 1 will take the value of obj.x, which means, take the x value of the first instance of object "obj" in priority list, sum 1 to it and put it on the value of x to every instance of the object "obj", making all of the objects result into having the same resulting x value, instead of summing 1 to its own value.
If this is applied by every object "obj", it will make all objects obj have the same resulting x value of the first object obj.x + instance_count.

I tested this condition by placing 5 Player objects on screen with a modified code when T is pressed:
Code:
Player.x++;
I moved them to different positions, and once T was pressed all of them had their x value reset to the x of the first Player object in priority summed by 5.

I don't think this is intended however, it seems like a low level programming problem, like a race condition of some sort.

That is an interesting result, because that means "." will just take the value of the first instance it can find if applied on the right side of an attribution, but will apply to every possible instance if applied on the left side, while "with()" will take the values from each individual instance used.
 
Last edited:

Dupletor

Member
@Simon Gust How am I supposed to read that chart? Not like an access takes 400 ms, how many accesses are there? 10 million?
(By the way, for the sake of the example, is array_length_1d so much faster than RAM memory access that it makes a difference in the long run?)
 
Last edited:

Simon Gust

Member
@Simon Gust How am I supposed to read that chart? Not like an access takes 400 ms, how many accesses are there? 10 million?
The chart I found here in this Thread
https://forum.yoyogames.com/index.php?threads/are-global-variables-worth-it.33787/

@Simon Gust(By the way, for the sake of the example, is array_length_1d so much faster than RAM memory access that it makes a difference in the long run?)
What do you mean by that? Do you mean that I should also shortcut it? The answer would be yes.
 

TsukaYuriko

☄️
Forum Staff
Moderator
The benchmark tool mentioned in the linked topic can be found here: http://gmc.yoyogames.com/index.php?showtopic=604444

With that said, the only real answer to this question lies within a full-scale benchmark. This means going through multiple iterations of the benchmark to get average r/w times for each operation as well as for a varying amount of operations performed, then ideally plotting the results to a graph to see where the falloff in performance gain/loss lies for which method(s). Even then, the result is still bound to your specific hardware configuration and PC usage at the given moment in time and should therefore be taken with a grain of salt. An entirely or even slightly different PC could produce entirely different results.
 
Z

zendraw

Guest
if you store an instance`s ID in a variable like this
var i=instance_create(x, y, o_object);
you will aways apply whatever with whichever method you decide, to that specific instance
i.x++;
with (i) {x++};
is the same thing and will apply to that specific instance, not all instances of that object.

if you access the name of the objeect in the resourse tree then it will apply to all instances of that object
o_object.x++;
with (o_object) {x++};
is the same thing, but applies to all INSTANCES of that object.

and finally as mentioned meny times, WITH is more optimal then "." but "." is nececery in certain cases where you cant pass variables thru WITH. like so

var i=50;
var ins=instance_create(x, y, o_oibject);
with (ins) {ammo+=other.i};

this wont work and will throw an unknown variable error so in this case you have no choise but to use "."

ins.ammo+=i;

also, logically, if you need to set 10+ variables, but only one of which are temporary, you can simply do this

ins.ammo+=i;
with (ins)
{
bla++;
bas++;
das++;
}

but you can also just make the variable local. i tend to make 1-2 variables "val" which means i store in them whatever and use them for different things, like temporary variables but you can freely use WITH by making them local.

Edit: reason why WITH is more optimal then "." is becouse you do the accessing process once with WITH and meny times with ".";

also another thing i need to mention. if you dont need the instance`s ID after you have created it, you dont need to store it in a variable and just do this
with (instance_create(x, y, o_object))
{
x++;
ammo+=other.val;
}
 

xDGameStudios

GameMaker Staff
GameMaker Dev.
actually: "." will apply to 1 instance only. and if no instance exists the game breaks!!
If so I'm sorry for my observation!! But as far as I know it hasn't always been like this (and I don't work with GMS in a while now)!

and while it works when writing:

Code:
my_object.temp = 20;
(sets temp variable on all instances of my_object to 20)

when reading it just doesn't work...

that is why:

Code:
my_object.x = my_object.x + 1;
because the reading (in the right side of the equation) doesn't know which instance to read from!!
 

TsukaYuriko

☄️
Forum Staff
Moderator
When in an instance context, using an object works differently for reading and writing.

When reading, an object index refers to the object's first instance.
When writing, an object index refers to all of its instances.

This behavior is intentional.
 

Dupletor

Member
if you access the name of the objeect in the resourse tree then it will apply to all instances of that object
o_object.x++;
with (o_object) {x++};
is the same thing, but applies to all INSTANCES of that object.

}
This is not true, because of the situation I described.
Code:
with(o_object) {x++};
will take the value of x of every instance and sum 1 to itself. (Just tested and confirmed)
Code:
o_object.x++;
will set all the values of x of every instance of o_object to the value of x of the first instance in priority list and sum 1 to them. (Tested and confirmed yesterday)

The codes do different things, due to what the moderator just said.
The code behaves like the moderator said, but because people think "x++" is only a write, it behaves different than it seems it should. "x++" includes a read and a write, each working as described separately.

However, why does "with(o_object)x++;" not behave like the moderator just said it would when reading "x" from "o_object"? Does it apply the calculations to take variables from to the self pointer?
 
Last edited:
Z

zendraw

Guest
This is not true, because of the situation I described.
Code:
with(o_object) {x++};
will take the value of x of every instance and sum 1 to itself. (Just tested and confirmed)
Code:
o_object.x++;
will set all the values of x of every instance of o_object to the value of x of the first instance in priority list and sum 1 to it. (Tested and confirmed yesterday)

The codes do different things, due to what the moderator just said.
The code behaves like the moderator said, but because people think "x++" is only a write, it behaves different than it seems it should. "x++" includes a read and a write, each working as described separately.

However, why does "with(o_object)x++;" not behave like the moderator just said it would when reading "x" from "o_object"?
what exactly are you reading? you reply to what i write sayng its wrong and then you write what im sayng. :D but yes i had to point out, reading the variable will only read from the first instance created, but we were talking about writing so i didnt think about that. alho id say its obvious ammo=o_object.val; wont read a sum of all instances of the object but a specific instance, which is the first one so it seems.
 
Top