Is X += Y faster then X = X + Y?

Heya, as I slowly micro optimizing im wondering, which is faster?

value = value + othervalue

or

value += othervalue

Would it be worth it to go through my code and change it (which would only take maybe 5-10 minutes) and what performance impact could it have?

1 Like

value += othervalue is faster bc less characters obviously

1 Like

You could test, but I would assume it falls under syntax sugar, so no difference other than how you type it.

Well, I prefer X += Y instead of X = X + Y. It is less to type, a smaller formula, and it just makes your scripts neater anyway. Plus, sense it indexes once I believe it is faster (it may not sense its running through Syntax sugar).

If you really want to do it then just do it, you’ll be happier.

1 Like

Don’t micro optimize, it’s a waste of time, x += y is just syntax sugar for x = x + y.

5 Likes

But I like micro-optimizing!! (As I said before it only takes me 5-10 minutes.) Plus if your indexing something wouldn’t it be faster to only index that once instead of twice?

+= is slower, I tested it a long time ago but it’s like nanoseconds slower, don’t you dare using the second variant because of nano optimization

1 Like

You wouldn’t get any tangible benefit from doing it, just don’t. If you want to switch for convenience sake go ahead, but as mentioned there won’t be any meaningful boost, if any. You should only optimize the parts of your code that need optimizing, not doing it just for the sake of doing it. You know the saying “if it ain’t broke don’t fix it”, the same applies here. If it ain’t need optimizing don’t optimize it.

It’s also unlikely that the way you increment your variable is your bottleneck.

5 Likes

You can benchmark it yourself using os.clock as it is it’s intended purpose.

-- Record the initial time:
local startTime = os.clock()
-- Do something you want to measure the performance of:
local a = 0
for i = 1, 5000000 do
	a += 1
end
-- Measure amount of time this took:
local deltaTime = os.clock() - startTime
print("Elapsed time shorthand syntax:" .. deltaTime)

-- Record the initial time:
local startTime = os.clock()
-- Do something you want to measure the performance of:
local a = 0
for i = 1, 5000000 do
	a = a + 1
end
-- Measure amount of time this took:
local deltaTime = os.clock() - startTime
print("Elapsed time not shorthand syntax: " .. deltaTime)
  16:33:27.637  Elapsed time shorthand syntax:0.024885643000744  -  Server  -  Script:10
  16:33:27.661  Elapsed time not shorthand syntax: 0.024271065998619  -  Server  -  Script:21

Currently getting results similar to @imKirda 0.0006 second difference for 5000000 iterations so it’s like 0.0006/5000000 which is 0.12 nano seconds slower. It’s probably inacurate because os.clock is only precise down to a microsecond which is 0.000001 seconds and it depends on how fast my computer is running it I believe. Of course, it’ll very but the difference in time is not significant at all waste of time as @sjr04 mentions yet it’s very interesting.

4 Likes

Like I have said before it only takes me 5 minutes, I simply want to know if it had much of a performance boost for indexing.

I could be entirely wrong on this, but IIRC, I’ve read somewhere that in some use cases, using += is faster than using something like:

local a = 0

while wait(1/30) do
    a = a + 1
end

What I mean by this is the idea of overhead via metatables and/or functions. Think indexing a table that has a really complex metastructure that goes through indexing even more tables and maybe calling some internal function(s). This is where you could see at least (?) twice the gain in speed.

From a face value, no - doing something like this won’t get you any worthwhile speed boost:

local a = 0

while wait(1/30) do
     a += 1
end

But if there was overhead to indexing a variable through a table, like nested metatable usage or function calls, then I believe that the overhead would be a detriment to the speed, having to essentially do all the work almost twice just for a read-only value.

Edit: I forgot to explain why I believe it’d be faster from Roblox’s internal perspective:

It would be faster because Roblox would internally cache both the pointer in memory to the table value as well as the returned value itself when specifically using += and use both to both set the value in memory as well as return whatever that would be plus whatever constant you’ve specified.

3 Likes

@hello42 is correct in their assessment, and I believe ROBLOX even stated this officially when they ported the syntax over, but your infrastructure would need to be pretty intense to begin with before you’d see anything meaningful. Like, extremely intense.

This example is very similar to @dthecoolest’s benchmark example, and it shows similar results despite involving a (fairly arbitrary) metatable structure.

local nest_base = {a=1}
local nest_tables = {}
nest_tables[1] = setmetatable({},nest_base)
nest_tables[1].__index = nest_base
for i=1,25 do
	local new_nest = setmetatable({},nest_tables[i])
	new_nest.__index = getmetatable(new_nest)
	nest_tables[i + 1] = new_nest
end
local nested_table = nest_tables[#nest_tables]

local start = os.clock()
for i=1,100000000 do
	nested_table.a = nested_table.a + 1
end
print(os.clock() - start)	--Takes 1.55 seconds on average

nested_table.a = 1

start = os.clock()
for i=1,100000000 do
	nested_table.a += 1
end
print(os.clock() - start)	--Takes 1.55 seconds on average
local nests = 0
local last_nest = getmetatable(nested_table)
while last_nest do
	nests += 1
	last_nest = getmetatable(last_nest)
end
print(nests)	--Prints 26; that is, 26 metatable layers

So, as you can see, even at 26 layers deep, there is no meaningful time savings from either syntax. Granted, this calculation is only a simple iteration without too much going on, but the point still stands that the usage of the syntax should predominantly come down to personal preference.

Ultimately, though, and this is true even to some extent of practices with noticeable performance impact, the goal should be to write legible code. Saving a few nanoseconds in runtime isn’t worth not knowing what your code is doing when you leave it on the back burner for 6 months and then finally come back to it. I know the “+=” versus “= +” syntax variation isn’t necessarily going to bring about that much confusion, but you should keep this mantra in the back of your mind when writing code.

3 Likes

So glad someone made a way more elegant looking code solution than I did from my tests! :smile:

I also found similar results with just nested tables.

    all values looped to the 5,000,000th
    
	a is the control, a non-nested local variable
		a += 1, (0.020683000002464 seconds)
		a = a + 1 (0.020264799997676 seconds)
		
		delta: 0.000418200004788 (negligible?)
		
	t is a nested table to the 20th degree
		t{20} += 1, (0.50851189999958 seconds)
		t{20} = t{20} + 1, (0.87945169999875 seconds)
		
		delta: t{20} += is 0.37093979999917 (~42.17% faster)

Comparing the data from five hundred thousand iterations to five million, the numbers just seem to factor up by 10, so at some point there is a taper off to how much more performant things get between the two methods. However, this also factors down when the nesting isn’t so large, if for example, the table was instead nested to the 19th degree. And that disparity goes all the way down as the nesting becomes less and less.

It’s sort of become a different question now, but I believe += has it’s place, and for most things, just + is probably just fine, and either may just be personal preference for the writer.

2 Likes

According to the assessment, it is merely a microoptimization and should only be considered as in the final decision. Thus meaning that you don’t necessarily have to optimize every single syntax that exists. The only time you would do the microoptimization is when the game is nearly finished. Run an A/B test to check whether something is better than the other.

Some microoptimizations are just sugar syntax as previously mentioned and only makes it “easier” to read. Sometimes the contrary. It is just elegant.

2 Likes

Is it faster? I don’t know. Other people have answered that question.

I can tell you that worrying about speed is worse than just a huge waste of your time. The people that advocate for doing stuff like x += y over x = x + y on the count of it being “faster” are outright infuriating. Little Joey isn’t going to stop playing your game because something lags 0.0000001 seconds behind – something literally thousands of times beyond human perception itself. In cases like these, do it because it makes your code easier to maintain, not because of performance.

Usually I only worry about performance if it has a notable impact on a small scale, as in it doesn’t require running it half a million times to actually get something the Lua VM can even count in the first place.

In my opinion, the sort of stuff you should worry about in raw Luau (granted, under circumstances where you can avoid these) is:

  • pcall
  • metatable __index / __newindex functions
  • (maybe) using pairs in favor of numeric loop.
  • getfenv() / setfenv() stuffs
3 Likes

He mean if the compiler calculate this faster, not if it‘s short or not. The world dosen‘t work like that.

1 Like

I just personally prefer +=, easier to read.

1 Like

There isn’t really a performance boost, you can test this out your self. It’s just better to keep your code small and organizable so value += n is preferred over value = value + n.