In my career, I've worked a lot with different programming languages, especially with C# and javascript.
During my years of development, I've face...
For further actions, you may consider blocking this person and/or reporting abuse
I really doubt this is right at all, and this is not a good experiment to show that it is right.
1) You're not recording the heap before hand, so it's impossible to know how much has actually changed
2) You're not running multiple experiments. The garbage collector is not deterministic, so you'll get slightly different numbers each time. At the least, you should be reporting an average over many trials.
3) You're logging to the console in this experiment. Logging to the console expends huge amounts of memory and CPU which are going to make the results far too variable to be useful.
For the record, when I tried measuring the difference, I saw no difference; the amount of memory that had been used by any single run was basically random, and neither was more or less than the other.
Remember the three rules of optimization:
1) Don't.
2) Don't, yet. (Experts only)
3) Profile before optimizing. Even if this experiment showed that variables inside loops use more memory, that wouldn't justify the blanket advice to not declare variables in loops, because that's probably not where most of your program is using its memory; instead of hurting readability and violating best-practices, you should find where your program is actually wasting most of its memory.
Seconding your answer.
Yes you're right, I'll keep your tips for the next time!
Don't wait until next time. This is harmful, bad advice. You should add a big fat disclaimer to the article that so you made mistakes here.
Please look further down the comments for a comment by Jan Hasebos. It would address your perception regarding the iterated declaration, while also respecting the variable scope of the for loop.
Really, you'd be better off saying the "bad" example is ok, while you feel the "good" example is better.
I added some thoughts below Jan to expand on this.
I want to buy you a beer
For loop-internal variables, this shouldn't actually save any memory on average. I mean, if the garbage collector is really stupid (most aren't), it might, but not much unless you've got a lot of variables inside the loop that are only ever primitives. OTOH, it should save some time, because you don't have to allocate memory on every loop iteration.
For the actual counter variable though, it's not as clear cut. In terms of runtime and memory usage, there should be near zero difference in the totals between these two code samples:
The reason is simple: Internally, that first part of the loop expression (the
i = 0
part) runs exactly once. So moving the counter declaration outside of the loop expressions just changes the scope, nothing else. Somewhat counter-intuitively, this may even make the loop run slower if you are accessing the counter inside the loop a lot (I know of no JS engine that actually has this issue, but a trivial naive implementation of the JS scoping rules would cause it to run slower).If, however, you can safely reuse the counter variable across multiple loops, then you might save some time this way, but you won't really save much space long-term. The important part there though is 'safely', you usually have to at least scope the declarations to the containing function so that you don't end up manipulating other loops states accidentally, so you're not likely to save much time either unless you're doing a lot of looping.
Came here to say this. Placing the
let
within the for expression doesn't mean it's being created every loop. It's only created once, it's more concise, and it's scoped to the for loops block. Unless you have good reason to (e.g. keeping track of a counter), to place it outside is just bad practice.Also, don't know about javascript, some compilers optimise your code so that variable declarations inside a loop when turn to machine code are placed outside the 'loop'.
You can never know how a compiler will ootimise your code. Interpreters are a whole different story. Correct me if I'm wrong. There are other things you can do to optimise your code and better manage memory. First thing is algorithm complexity and storing excess data or use blocks of code so you limit the life of a variable and etc.
There's definitely more important optimisations than worrying about a
for
loop. Unless you are looping through tens of thousands of objects - bit that's a whole different story.If it were almost anything but memory allocation, I would agree wholeheartedly. Allocating memory, however, is literally one of the slowest runtime operations possible in pretty much any language you care to name (coincidentally, this is most of why C++'s
std::string
is so slow compared to C-style strings, pretty much any call that 'mutates' a string involves allocating memory for a new one).The exact benefit may not be huge in terms of time, but it's a good habit to just write optimal code in cases like this where it's easy.
There are indeed other things you can do to optimize your code, but eliminating memory allocations (and de-allocations) is one of the easier ones that's consistently a win in most languages. That's one of the other reasons to group your variable declarations at the top of a function aside from making the code easier to read, some runtime environments and compilers will actually be able to further optimize things so that there are fewer allocations that need to be made that way.
Look, this article needs to be taken down. It's very harmful to novice programmers and more experienced programmers will probably just leave a comment saying "you're wrong". That being said, I feel bad for the author. He likely has no idea that this is bad advice and this is all probably discouraging. My advice for the author: please take the article down or revise it so that beginners don't draw incorrect conclusions. Afterwards, write your next article! I'd love to see you write about frontend or something else you're interested in!
Why? JavaScript has automatic garbage collection mechanism.
Yes sorry, I mean than "you cannot manually deallocate resources" like c# or c++ malloc or free
Sure you can, if you
null
an Object then it will be marked for GC. It may not happen immediately, but when the GC runs it will be cleaned up.developer.mozilla.org/en-US/docs/W...
C# has garbage collection and no way to manually free resources. It works the same as javascript, you can set all references to an object to
null
and then it will eventually be garbage collected. You can also force the garbage collector to run, but that is highly discouraged in almost all circumstances.Unfortunately we just have to trust that is what is happening but it's okay, we don't want to panic anyone. Can you see what I did there.
Just don't write in JavaScript if you need fast and memory efficient code.
This thing is premature optimization. You should prefer code clarity over efficienty until you absolutely need last one (about 1% of your code I suppose).
Declaring variables outside of your loop to use inside of a loop could cause unintended consequences if the code in the loop is complicated. Reusing variables might seem efficient until you need to fix a bug introduced by another developer.
Unless performance is really essential and in this case it's probably negligible, writing cleaner code is more important imo.
Pretty much everything here is wrong.
The iterator should be stack allocated, and is only initialized once anyway.
The logString variable is assigned to a new value each iteration and goes out of scope at the end, or at least gets reassigned. There aren't 1000 variables with heap string references waiting to be deallocated when the loop ends.
There is an excellent explanation by v8 developers of how memory allocation works in v8 JS engine.
I would read this before anyone jumps to conclusions.
Whoa, this is crazy. I have always dismissed the declaration inside the loop having a very minimal performance impact. Apparently my assumptions were wrong.
Thanks for this! Will definitely take note of this from here on out.
That's because it is incorrect. Please read the rest of the comments in this article for better explanations.
Thanks for the heads up!
Thanks a lot! Check this video from Unity, is for C# but some principles could be applied to general programming languages, it shows a lot of data optimization and performance boost using the Data-Driven programming pattern
Thanks! I definitely will watch it.
Please don't do this and take this article down. As others have mentioned, the experiment is flawed.
Don't prematurely optimize. It can lead to a number of problems:
Don't complicate your code unless absolutely necessary. Follow the KISS principal.
I recently found myself reviewing code from a senior software engineer that was filled with premature optimizations. It was very hard to read and created an abundance of code for what purpose? Just to save a negligible amount of time - we're talking far less than a millisecond. Orders of magnitude less than your standard network delay.
Don't be that engineer.
Don't encourage others to be that engineer.
The figures you quote there seem excessive. To be honest, I don't know javascript but every half-decent language I've ever used would consider logstring as going out of scope at the end of each loop iteration in the first version, so would free/deallocate any memory that was acquired at its declaration.
Also, what's the effect if you do:
let logString = 'Current is: ';
let i = 0;
for (i = 0; i < 1000; i++) {
console.log(logstring + i);
}
console.log('%o', window.performance.memory);
Dr. Strangeoptimization or: How I Learned to Stop Worrying and Love the Compiler
Like several people have said, this article needs to be updated with a disclaimer that it isn't accurate and the tests are far from comprehensive. Folks bookmarking this article are being mislead, and it's unfortunate for newer developers.
I couldn't understand this. Why does not garbage collection handle unused memory space? It usually clears when access to a specific location is not possible. I also never saw something like this in any complexity analysis.
Since you mentioned C#, it may be worth noting that you can define a C# variable within a loop without changing the resulting IL (the code that's actually run by the VM) at all. This is very easy to test.
However, there are instances, such as when using that variable within a lambda, in which this isn't true. That said, more often than not you actually should declare your variables inside the loop in C# so they are scoped properly.
Thank you! This is exactly what I was looking to add.
I see what the OP is attempting to draw attention to: instantiating the variable every iteration seems wasteful... Of something. He drew attention to the one thing that seemed to stand out, memory. But in truth it's not that simple, as the comments have shown.
The better answer, if loop declaration us bothering you, is to put the variable declaration in a spot that it only happens once. Either in the declarative part of the if, like in the above comment, or the more verbose way of using an if to declare the variable on first run.
I suppose my question would be, how much garbage does it create if the "bad" loop were to run 1 million times? What about in a complex situation where the GC is somehow occupied, and this loop runs 1 million times?
For sure, more testing and fuzzing is needed before coming to a conclusion regarding the "bad" way.
Garbage collected 😉
You're implicitly assuming that JS is allocating stack variables similar to how a compiled language like C# does it. The interpreter in JS is running at a much higher level and if a variable is declared inside a loop it will effectively run the code as if the variable were declared outside. It won't do a reallocation like you would see in .NET bytecode.
Although it's really great to point out and discuss low level performance concerns for things like loops...
The majority of the time it's better to have maintainable and readable code over optimized code. Compilers and garbage collectors usually do a good job most of the time!
IMO creating variables outside a loop for the sake of optimization adds code smells for little to no benefit!
JavaScript hoists all function variables on top of the function. You can even define a variable at the end and it will still work. Also there is no block scope variables in JavaScript. Sorry but this article is wrong.
Nice one ...have the habit of doing this. Shall change this from now onwards.
Please read the other comments before you change your habit... There is more to this story, and the "good" snippet in the article is flawed.
There's no need to do that. Please read the rest of the comments here, as the article is not really correct.
There’s a ‘static’ declerator in C, so I guess it’s not in the JS, right?
Wtf dude delete it