generic image
Processing...
  • Games
  • Catalog
  • Develop
  • Robux
  • Search in Players
  • Search in Games
  • Search in Catalog
  • Search in Groups
  • Search in Library
  • Log In
  • Sign Up
  • Games
  • Catalog
  • Develop
  • Robux
   
ROBLOX Forum » Game Creation and Development » Scripters
Home Search
 

Re: Efficiency Misconceptions

Previous Thread :: Next Thread 
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
01 Jan 2016 05:55 AM
Efficiency Misconceptions
In order of most common to least common (from what I've seen, at least)

1) Declaring a variable outside a loop is more efficient than declaring it inside a loop because you don't have to create a variable.
-> This is wrong. In terms of speed, they're the exact same because of how variables work internally in Lua. However declaring a variable outside the loop actually lets the last value leak which can hinder the GC from ever collecting garbage (depending on what you are doing) and may cause tiny memory leaks (which can build up, depending on what you are doing). Also, in my opinion, it looks cleaner to declare the variable inside the loop instead of outside the loop.

2) Using "next" is more efficient than using "pairs" in generic for loops.
-> While this is technically true, the speed difference is insignificant (unless you have a loop which has a loop like this in it, and so on). Realistically, "pairs" is actually "next in disguise" and you are actually using "next" implicitly when you use "pairs" explicitly. For each of your generic for loops, using "pairs" only costs a single extra function call as opposed to using "next" and something this small should not be considered an optimization in a language like Lua. In addition, it would be better to use a numerical for loop if you can instead of a generic for loop in general if you can (and if you do it properly). In a common example, say iterating through an array (a table that has no non-integer keys and all keys are ordered from 1, and has no holes) like those returned from the GetChildren function and whatnot, it seems to be 2x more efficient to use a numerical for loop.

3) Using a loop is more efficient than explicitly doing something over and over in Lua.
-> Loops make for shorter and better organized code, but that doesn't make it faster. The misconception in itself explains what is wrong with it in the first place; whether you use a loop or do something over and over, whatever you are repeatedly doing is done from Lua either way. This technically makes loops (and functions) slower, but the different is practically insignificant. Programming is really a balance of efficiency, readability, and maintainability; focusing on a single aspect is detrimental. Use functions and loops because reusing code makes for less required memory and typically makes your code more readable.

4) Shorter code is better code (this includes the misconception that 'semicolons' making your code slower).
-> This is obviously false, anyone with a basic knowledge of any programming language can tell you this. This implies that "local myVar = 10" should be changed to "m=10" which actually yields less efficient code. In a more rational sense, some say that shorter variable names (this includes function names, parameter names, etc.) are more efficient. While technically they are faster during compile-time, the benefit is far more than just insignificant considering your code is going to be compiled once, not many many times and that a simple "read next character" call from the compiler is very very efficient. As I said before, readability and maintainability is important and the duration at which your code compiles is not important in any way considering the Lua compiler is quick and your code is going to be compiled before you can even notice anything has happened. Technically your global variable names are actually stored meaning they will have to be utilized at runtime, but in that case it'd be far, far more efficient to just make it a local variable (if you can). Computers are fast, the time at which you read a character from a buffer is virtually 0.

5) Using the "_G" table is inefficient.
-> Using the "_G" table is just as efficient as indexing/writing to any other table (that is referenced to by a global variable). _G is just a regular Lua table, and in Roblox: all scripts on that same machine can access it (as opposed to it just referencing the global environment as it does in "Vanilla Lua"). Saying that accessing "_G" is inefficient is saying that accessing the "print" function or the "Instance" table (where Instance.new exists) is inefficient. It can actually be really efficient and save tons of memory if you reuse functions in many different scripts. Instead of creating many identical functions across separate scripts, you can create it in a single script and store a reference to it in "_G" in which you can read it from any script that wants to utilize it. Obviously ModuleScripts would be "better" in some cases (in that it's a much better way to be organized and keep "_G" clean if you need it for something else) but accessing "_G" is not "magically less efficient" than accessing any other global variable.

6) Testing a value instead of comparing a value is more efficient ("if not x" as opposed to "if x == false" or "if x == nil").
-> While technically it is more efficient, the benefit is more than negligible. In my opinion the first one is more readable but if the second one looks better to you, switching to the first one "because it's more efficient" is not something you should do. Also, these both do different things; in some cases you have to use the latter (checking a value to see if it's exactly nil).

7) This one is pretty Roblox specific: "while wait() do" is faster than "while true do" and calling "wait" somewhere within that loop.
-> False, technically the second one is actually more efficient (but of course, almost negligible). In my opinion the second one can actually be less misleading as not everyone knows that the "wait" function returns something that is non-falsey and can make the first look like "magic" to beginners. Not only that, but if you want to yield after everything happens as the first method forces it to yield before, it's much easier to do that with the second method. Of course if the first one looks better to you, use it.

I may expand on this later on, also please feel free to ask questions and contribute if you can. And if you find any error (whether it's a typo or an actual inaccuracy) please let me know as soon as you can. You'll be given credit regardless of how you contribute.
Report Abuse
tyzone is not online. tyzone
Joined: 16 Aug 2008
Total Posts: 1726
01 Jan 2016 06:01 AM
Great post overall. I don't have any misconceptions to offer, but do you know if there exists a similar document that gives you little tips and tricks about small syntax modifications that can change the performance significantly?


eww no pink shaggy
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
01 Jan 2016 06:05 AM
Well things like that are very situation-specific (by syntax I assume you just mean in general) but typically the most known tips are: use local variables, don't "hog the resources" (do too many things at a given time) if you can avoid it (the "using wait wisely" Roblox blog post will help you understand what I mean), and planning out your code can help you out big time.
Report Abuse
BFFstick00 is not online. BFFstick00
Joined: 25 Oct 2010
Total Posts: 800
01 Jan 2016 06:20 AM
I never knew that people thought that was efficient.
Report Abuse
DrHaximus is not online. DrHaximus
Joined: 22 Nov 2011
Total Posts: 8410
01 Jan 2016 06:27 AM
"technically the second one is actually more efficient (but of course, almost negligible)"

i don't know if 'negligible' is the right word here. the lack of sleeping after every iteration can massively improve performance (in terms of time) in the circumstances of:
1) heavy calculation, lots of iteration
2) the loop definitely breaks eventually
Report Abuse
DrHaximus is not online. DrHaximus
Joined: 22 Nov 2011
Total Posts: 8410
01 Jan 2016 06:27 AM
you know what? i misread that.
please ignore.

good post.
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
01 Jan 2016 06:59 AM
'this includes the misconception that 'semicolons' making your code slower'

I've heard this as 'semicolons make your code faster because the compiler doesn't add them in'

I've never heard of semicolons making it slower.



Also isn't there some misconception on if methods are faster or not?
Report Abuse
BFFstick00 is not online. BFFstick00
Joined: 25 Oct 2010
Total Posts: 800
01 Jan 2016 07:07 AM
Lua is an interpreted language, not a compiled language. However the language it is made in(C) is a compiled language.
Report Abuse
WolfgangVonPrinz is not online. WolfgangVonPrinz
Joined: 24 Oct 2013
Total Posts: 4656
01 Jan 2016 07:28 AM
Shorter code is better in terms of quantity of lines (Lines like that of python, which we use the template of in Lua, but serve no actual purpose other than it's easier to look at). Shorter code is better as it is executed faster (Again, in terms of lines), often but not always easier to understand, easier to edit, and quicker to type.

To clarify, what I mean by lines

while wait() do
print("This is 3 lines")
end


while wait() do print("This is 1 line, but the same as 3.") end
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
01 Jan 2016 02:01 PM
"I've heard this as 'semicolons make your code faster because the compiler doesn't add them in'"
The compiler won't add in semi-colons, it uses whitespace to denote an end of a statement.

"Also isn't there some misconception on if methods are faster or not?"
Well methods in themselves are supposed to be more efficient, but typically a method call requires an object lookup meaning it can become much less efficient if you have to do a lot of lookups.

"Lua is an interpreted language, not a compiled language. However the language it is made in(C) is a compiled language."
Lua is interpreted, but it's compiled into an intermediate form called Lua bytecode because bytecode is far easier to interpret.

"Shorter code is better as it is executed faster"
I don't understand what you mean "executed faster", because literally that means _faster to execute_ which is false.
Report Abuse
JarodOfOrbiter is not online. JarodOfOrbiter
Joined: 17 Feb 2011
Total Posts: 20029
01 Jan 2016 02:09 PM
"Well methods in themselves are supposed to be more efficient, but typically a method call requires an object lookup meaning it can become much less efficient if you have to do a lot of lookups."

Could you give an example? I've been confused for quite some time on this concept.
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
01 Jan 2016 02:17 PM
Here's a simple example.

This:
str:sub(x, y);
Will be slightly less efficient than storing a reference to string.sub over the long run because you won't need to actually "get the sub function from the string" (a couple of implicit table lookups in this case).
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
01 Jan 2016 02:19 PM
Of course in this case, the speed difference will only really be visible if you do it PLENTY of times. In a case like this it would be better to use a method since it is easier to read (at least for me). But in a case of something like:
a.b.c.d:e(f)

You will see a significant difference over the long run (you can test this by having a loop doing it a bunch of times and see how much time has passed).
Report Abuse
WolfgangVonPrinz is not online. WolfgangVonPrinz
Joined: 24 Oct 2013
Total Posts: 4656
01 Jan 2016 02:29 PM
What I meant by faster is that it can read 5 lines faster than 20 assuming the content is the same time length to execute
Report Abuse
chimmihc is not online. chimmihc
Joined: 01 Sep 2014
Total Posts: 17143
01 Jan 2016 02:38 PM
All that is handled at compile time, the speed it actually executes is not effected.
Report Abuse
rvox is not online. rvox
Joined: 18 Feb 2011
Total Posts: 5380
01 Jan 2016 02:42 PM
line breaks count as one character, so the difference is negligible

also, a lot of the time, you need some character separator in between

what i said is probably right, dont quote me
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
01 Jan 2016 02:45 PM
"What I meant by faster is that it can read 5 lines faster than 20 assuming the content is the same time length to execute"
If you read what I posted, you should have read that compile-time is not important, because it's done once and reading a single character is stupid fast. And as chimmihc said, all this affects is the length at which the code is compiled, but "affects" is actually not the correct term because of how insignificant it is.
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
01 Jan 2016 02:45 PM
And also what rvox said.
A newline and a space are both a single character, so putting things on a single line will actually not affect it in any way.
Report Abuse
WolfgangVonPrinz is not online. WolfgangVonPrinz
Joined: 24 Oct 2013
Total Posts: 4656
02 Jan 2016 01:51 PM
Bump. This was interesting
Report Abuse
mudkip99 is not online. mudkip99
Joined: 17 Jun 2008
Total Posts: 3362
02 Jan 2016 01:58 PM
Even with excess whitespace, it's all removed at compiletime, anyway. With an interpreted language like Lua, it makes a bit more difference (almost 0, completely imperceptible to a human, but still some since it has to recompile it every time it runs), but you could have a ten line script and a ten million line script whose only differences are newlines/spaces, and you would see no difference in performance at runtime whatsoever.
Report Abuse
heavylifterman192 is not online. heavylifterman192
Joined: 18 Oct 2015
Total Posts: 201
02 Jan 2016 09:22 PM
Nice post, cntkillme! I really like and agree with most of the points, so please forgive that I have to point one thing out: while you made an explicit implication that semicolons don't make code slower, logic is to the contrary. String parsing functions are among the slowest, so it only makes sense that given more length it takes longer. Additionally, semicolons end statements, so Lua can get a bit confused (I won't go too much into detail but imagine putting two 'end's after one if without an error.) Other than that, not too much to complain about! I hope the community takes these into consideration before embarking upon meaningless quests for efficiency while sacrificing all other aspects of their code.
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
02 Jan 2016 09:26 PM
Even though I know you are trolling, others may not.
"String parsing functions are among the slowest, so it only makes sense that given more length it takes longer. Additionally, semicolons end statements, so Lua can get a bit confused (I won't go too much into detail but imagine putting two 'end's after one if without an error.)"
Obviously string parsing functions in C are not slow considering they are simple array lookups. Semicolons are optional, and 'putting two ends after one if' is going to result with an error regardless of semicolons.
Report Abuse
dennis96411 is not online. dennis96411
Joined: 06 Mar 2009
Total Posts: 1079
02 Jan 2016 09:38 PM
Do the tips from "Lua Performance Tips" by Roberto Ierusalimschy help?
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
02 Jan 2016 09:39 PM
Yes, that's a really good PDF. This thread is merely just to clear up some misinformation, not really inform how to write more efficient code so I'd recommend everyone to take a look at that if they care.
Report Abuse
dennis96411 is not online. dennis96411
Joined: 06 Mar 2009
Total Posts: 1079
02 Jan 2016 09:46 PM
I need your expert opinion. We know the following does show some performance improvement:

local mytable = {}
local table_insert = table.insert

for i = 1, 100000 do
table_insert(mytable, i)
end

But what if we were to call it from a deeper scope?

local mytable = {}
local table_insert = table.insert

for a = 1, 2 do
for b = 1, 2 do
...
table_insert(mytable, f)
...
end
end

It doesn't necessarily have to be loops; it could be enclosing functions. Does this slow down the lookup for the function on the stack?
Report Abuse
Previous Thread :: Next Thread 
Page 1 of 1
 
 
ROBLOX Forum » Game Creation and Development » Scripters
   
 
   
  • About Us
  • Jobs
  • Blog
  • Parents
  • Help
  • Terms
  • Privacy

©2017 Roblox Corporation. Roblox, the Roblox logo, Robux, Bloxy, and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.



Progress
Starting Roblox...
Connecting to Players...
R R

Roblox is now loading. Get ready to play!

R R

You're moments away from getting into the game!

Click here for help

Check Remember my choice and click Launch Application in the dialog box above to join games faster in the future!

Gameplay sponsored by:
Loading 0% - Starting game...
Get more with Builders Club! Join Builders Club
Choose Your Avatar
I have an account
generic image