I have the following code:
for (int i = 0; i < array.length; i++) {
int current = array[i];
//do something with current...
}
and the function
int current = 0;
for (int i = 0; i < array.length; i++) {
current = array[i];
//do something with current...
}
My question is, do they have the same memory footprint??
I mean, it is clear that the 2nd function will only have 1 variable "current". But how about the first function. Lets assume array has length 1000, does this mean 1000 integeger variables "current" will be created in the inner loop?
No difference.But IMHO You should generally give variables the smallest scope you can. So declare it inside the loop to limit its scope. You should also initialize variables when they are defined, which is another reason not to declare it outside the loop.
They have exactly the same footprint. They even have (without regard to some variable numbering) the exact same bytecode. You can try by putting this in a Test.java, compile it and disassemble it with "javap -c Test"
HTH :)
There is no difference. The compiler is smart enough to generate similar bytecode for both cases by making the right optimizations.
If you want to use the variable outside the loop, declare it outside it, otherwise, in order to give the variable the smallest scope, declare it inside the loop (and consider making it final in this case).
The two code fragments are equivalent. May even compile to the exact same bytecode (someone will decompile it). Each just creates a single local variable (that is reused in the loop).
Related
I am wondering, from perspective of memory usage, performance and clean code, is it better to initialize variable inside or outside the loop.
For example, below I show two options using variable myInt in a for loop.
Which options is better?
I have a intuition on which option does what, but I want a true "Java" clarification which option is better for 1) Performance, 2) Memory and 3) Better code style.
Option 1:
int myInt = 0;
for (int i =0; i<100; i++){
some manipulation here with myInt
}
Option 2:
for (int i =0; i<100; i++){
int myInt = 0;
some manipulation here with myInt
}
Variables should always* be declared as locally as posible. If you use the integer inside the loop only, it should be declared inside the loop.
*always - unless you have a really good and proven reason not to
If you want to use the myInt within the for loop Option2 is better.
You want to use it outside the loop Option1 is better.
Using variables in smallest scope is better option.
Well, these two options provide two different use cases:
The value of of myInt in Option2 will reset on every loop iteration, since it's scope is only within the loop.
Option1 is the way to go, if you want to something with myInt within the loop and do something with it after the loop.
I personally wouldn't care about memory or performance here, use the scope you need.
This question already has answers here:
Difference between declaring variables before or in loop?
(26 answers)
Closed 7 years ago.
I was wondering which one is better in term of memory allocation. I know at this scale these would not be any different since creating a variable would take so little memory, but I wanted to get used to coding the better way for the future.
public static void test(Scanner input, int[] arr){
for (int i = 0; i < 5; i++){
int age = input.nextInt();
arr[i] = age;
}
or
public static void test(Scanner input, int[] arr){
int age = null;
for (int i = 0; i < 5; i++){
age = input.nextInt();
arr[i] = age;
}
}
Declaring the variable before the for loop would only allocate one place in memory for all the values I set it to, correct? But if I declare the variable in the for loop, will 5 different places in memory be allocated or just one that will be overwritten when the for loop is run again?
I should also state that the variable age will not be used anywhere else but inside that for loop.
Thanks.
Shouldn't make any difference, so my suggestion is limit it to the required scope (i.e. option 1) - also int age = null; is a bit misleading - makes you read like it's a pointer even though it isn't. int age = 0; would be a bit clearer.
many discussion: already there: Difference between declaring variables before or in loop?
There are others factors:
static, global.
In general, the more performance, the less readable, the less safe
The difference in performance, if not eliminated by the compiler's optimization, would not be noticeable at all. What is noticeable, and should be taken into account, is the readability of your code.
Declaring the variable before the loop only makes the code harder to read, and also pollutes the namespace outside the loop. As a general rule of thumb, declare your variables in the smallest scope where you need them.
Don't use temporary variable yourself, this one is better:
public static void test(Scanner input, int[] arr){
for (int i = 0; i < 5; i++){
arr[i] = input.nextInt();
}
}
If variable will be used only within cycle, then declare it within cycle, in order to pollute function's namespace.
Which is better, first or second?
From a performance perspective, you'd have to measure it. (And in my opinion, if you can measure a difference, the compiler isn't very good).
From a maintenance perspective, first is better. Declare and initialize variables in the same place, in the narrowest scope possible. Don't leave a gaping hole between the declaration and the initialization, and don't pollute namespaces you don't need to.
What is better in for loop
This:
for(int i = 0; i<someMethod(); i++)
{//some code
}
or:
int a = someMethod();
for(int i = 0; i<a; i++)
{//some code
}
Let's just say that someMethod() returns something large.
First method will execute someMethod() in each loop thus decreasing speed, second is faster but let's say that there are a lot of similar loops in application so declaring a variable vill consume more memory.
So what is better, or am I just thinking stupidly.
The second is better - assuming someMethod() does not have side effects.
It actually caches the value calculated by someMethod() - so you won't have to recalculate it (assuming it is a relatively expansive op).
If it does (has side effects) - the two code snaps are not equivalent - and you should do what is correct.
Regarding the "size for variable a" - it is not an issue anyway, the returned value of someMethod() needs to be stored on some intermediate temp variable anyway before calculation (and even if it wasn't the case, the size of one integer is negligible).
P.S.
In some cases, compiler / JIT optimizer might optimize the first code into the second, assuming of course no side effects.
If in doubt, test. Use a profiler. Measure.
Assuming the iteration order isn't relevant, and also assuming you really want to nano-optimize your code, you may do this :
for (int i=someMethod(); i-->0;) {
//some code
}
But an additional local variable (your a) isn't such a burden. In practice, this isn't much different from your second version.
If you don't need this variable after loop, there is simple way to hide it inside:
for (int count = someMethod (), i = 0; i < count; i++)
{
// some code
}
It really depends how long it takes to generate the output of someMethod(). Also the memory usage would be the same, because someMethod() first has to generate the output and stores this then. The second way safes your cpu from computing the same output every loop and it should not take more memory. So the second one is better.
I would not consider the memory consumption of the variable a as a problem as it is an int and requires 192 bit on a 64 bit machine. So I would prefer the second alternative as it execution efficiency is better.
The most important part about loop optimizations is allowing the JVM to unroll the loop. To do so in the 1st variant it has to be able to inline the call to someMethod(). Inlining has some budget and it can get busted at some point. If someMethod() is long enough the JVM may decide it doesn't like to inline.
The second variant is more helpful (to JIT compiler) and likely to work better.
my way for putting down the loop is:
for (int i=0, max=someMethod(); i<max; i++){...}
max doesn't pollute the code, you ensure no side effects from multiple calls of someMethod() and it's compact (single liner)
If you need to optimize this, then this is the clean / obvious way to do it:
int a = someMethod();
for (int i = 0; i < a; i++) {
//some code
}
The alternative version suggested by #dystroy
for (int i=someMethod(); i-->0;) {
//some code
}
... has three problems.
He is iterating in the opposite direction.
That iteration is non-idiomatic, and hence less readable. Especially if you ignore the Java style guide and don't put whitespace where you are supposed to.
There is no proof that the code will actually be faster than the more idiomatic version ... especially once the JIT compiler has optimized them both. (And even if the less readable version is faster, the difference is likely to be negligible.)
On the other hand, if someMethod() is expensive (as you postulate) then "hoisting" the call so that it is only done once is likely to be worthwhile.
I was a bit confused about the same and did a sanity test for the same with a list of 10,000,000 integers in it. Difference was more than two seconds with latter being faster:
int a = someMethod();
for(int i = 0; i<a; i++)
{//some code
}
My results on Java 8 (MacBook Pro, 2.2 GHz Intel Core i7) were:
using list object:
Start- 1565772380899,
End- 1565772381632
calling list in 'for' expression:
Start- 1565772381633,
End- 1565772384888
Ive got one simple question. Normally I write code like this:
String myString = "hello";
for (int i=0, i<10; i++)
{
myString = "hello again";
}
Because I think the following would not be good style cause it would create too many unnecessary objects.
for (int i=0, i<10; i++)
{
String myString = "hello again";
}
Is this even correct? Or is this just the case when Ive got an explicit object like an object from a class I created? What if it was a boolean or an int? What is better coding style? Instantiate it once before the loop and use it in the loop or instantiate it every time in the loop again? And why? Because the program is faster or less storage is used or...?
Some one told me, if it was a boolean I should instantiate it directly in the loop. He said it would not make a difference for the heap and it would be more clear that the variable belongs inside the loop. So what is correct?
Thanks for an answer! :-)
====
Thanks for all your answers!
In conclusion: it is preferable to declare an object inside the smallest scope possible. There are no performance improvements by declaring and instantiating objects outside the loop, even if in every looping the object is reinstantiated.
No, the latter code isn't actually valid. It would be with braces though:
for (int i=0; i<10; i++)
{
String myString = "hello again";
}
(Basically you can't use a variable declaration as a single-statement body for an if statement, a loop etc.)
It would be pointless, but valid - and preferable to the first version, IMO. It takes no more memory, but it's generally a good idea to give your local variables the narrowest scope you can, declaring as late as you can, ideally initializing at the same point. It makes it clearer where each variable can be used.
Of course, if you need to refer to the variable outside the loop (before or afterwards) then you'll need to declare it outside the loop too.
You need to differentiate between variables and objects when you consider efficiency. The above code uses at most one object - the String object referred to by the literal "hello again".
As Binyamin Sharet mentioned, you generally want to declare a variable within the smallest scope possible. In your specific examples, the second one is generally preferable unless you need access to the variable outside your loop.
However, under certain conditions this can have performance implications--namely, if you are instantiating the same object over and over again. In your particular example, you benefit from Java's automatic pooling of String literals. But suppose you were actually creating a new instance of the same object on every iteration of the loop, and this loop was being executed hundreds or thousands of times:
for (int i=0, i<1000; i++)
{
String myString = new String("hello again"); // 1000 Strings are created--one on every iteration
...
}
If your loop is looping hundreds or thousands of times but it just so happens that you're instantiating the same object over and over again, instantiating it inside the loop is going to result in a lot of unnecessary garbage collection, because you create and throw away a new object on every iteration. In that case, you would be better off declaring and instantiating the variable once outside of the loop:
String myString = new String("hello again"); // only one String is created
for (int i=0, i<1000; i++)
{
...
}
And, to come full circle, you can manually limit the scope by adding extra braces around the relevant section of code:
{ // Limit the scope
String myString = new String("hello again");
for (int i=0, i<1000; i++)
{
...
}
}
Seems like you mean declare, not instantiate and in general, you should declare a variable in the smallest scope required (in this case - in the loop).
if you are going to use the variable outside the for loop, then declare it out side, otherwise its better to keep the scope to minimum
The problem with the second is you create object and someone (the GC) has to clean them, of course for a 10 iteration it is unimportant.
BTW in your specific example I would have wrote
String myString = null;
final String HELLO_AGAIN="hello again";
for (int i=0; i<10; i++)
myString = HELLO_AGAIN;
Unless value is changed, you should definitely instantiate outside of the loop.
The problem here is that String is an immutable object: you cannot change the value of a string, only you can create new String objects. Either way, if your goal is to assign a variable a new object instance, then limit your scope and declare it inside the body of your loop.
If your object is mutable, then it would be reasonable to reuse the object in every next iteration of the loop, and just change those attributes you need. This concept is used to run the same query multiple times, but with different parameters, you use a PreparedStatement.
In the extreme case, you would even maintain pools of objects which can be shared within the whole application. You create additional objects as you run out of resources, you shrink if you detect a reasonable amount of non-use. This concept is used to maintain a Connection Pool.
String s = "";
for(i=0;i<....){
s = some Assignment;
}
or
for(i=0;i<..){
String s = some Assignment;
}
I don't need to use 's' outside the loop ever again.
The first option is perhaps better since a new String is not initialized each time. The second however would result in the scope of the variable being limited to the loop itself.
EDIT: In response to Milhous's answer. It'd be pointless to assign the String to a constant within a loop wouldn't it? No, here 'some Assignment' means a changing value got from the list being iterated through.
Also, the question isn't because I'm worried about memory management. Just want to know which is better.
Limited Scope is Best
Use your second option:
for ( ... ) {
String s = ...;
}
Scope Doesn't Affect Performance
If you disassemble code the compiled from each (with the JDK's javap tool), you will see that the loop compiles to the exact same JVM instructions in both cases. Note also that Brian R. Bondy's "Option #3" is identical to Option #1. Nothing extra is added or removed from the stack when using the tighter scope, and same data are used on the stack in both cases.
Avoid Premature Initialization
The only difference between the two cases is that, in the first example, the variable s is unnecessarily initialized. This is a separate issue from the location of the variable declaration. This adds two wasted instructions (to load a string constant and store it in a stack frame slot). A good static analysis tool will warn you that you are never reading the value you assign to s, and a good JIT compiler will probably elide it at runtime.
You could fix this simply by using an empty declaration (i.e., String s;), but this is considered bad practice and has another side-effect discussed below.
Often a bogus value like null is assigned to a variable simply to hush a compiler error that a variable is read without being initialized. This error can be taken as a hint that the variable scope is too large, and that it is being declared before it is needed to receive a valid value. Empty declarations force you to consider every code path; don't ignore this valuable warning by assigning a bogus value.
Conserve Stack Slots
As mentioned, while the JVM instructions are the same in both cases, there is a subtle side-effect that makes it best, at a JVM level, to use the most limited scope possible. This is visible in the "local variable table" for the method. Consider what happens if you have multiple loops, with the variables declared in unnecessarily large scope:
void x(String[] strings, Integer[] integers) {
String s;
for (int i = 0; i < strings.length; ++i) {
s = strings[0];
...
}
Integer n;
for (int i = 0; i < integers.length; ++i) {
n = integers[i];
...
}
}
The variables s and n could be declared inside their respective loops, but since they are not, the compiler uses two "slots" in the stack frame. If they were declared inside the loop, the compiler can reuse the same slot, making the stack frame smaller.
What Really Matters
However, most of these issues are immaterial. A good JIT compiler will see that it is not possible to read the initial value you are wastefully assigning, and optimize the assignment away. Saving a slot here or there isn't going to make or break your application.
The important thing is to make your code readable and easy to maintain, and in that respect, using a limited scope is clearly better. The smaller scope a variable has, the easier it is to comprehend how it is used and what impact any changes to the code will have.
In theory, it's a waste of resources to declare the string inside the loop.
In practice, however, both of the snippets you presented will compile down to the same code (declaration outside the loop).
So, if your compiler does any amount of optimization, there's no difference.
In general I would choose the second one, because the scope of the 's' variable is limited to the loop. Benefits:
This is better for the programmer because you don't have to worry about 's' being used again somewhere later in the function
This is better for the compiler because the scope of the variable is smaller, and so it can potentially do more analysis and optimisation
This is better for future readers because they won't wonder why the 's' variable is declared outside the loop if it's never used later
If you want to speed up for loops, I prefer declaring a max variable next to the counter so that no repeated lookups for the condidtion are needed:
instead of
for (int i = 0; i < array.length; i++) {
Object next = array[i];
}
I prefer
for (int i = 0, max = array.lenth; i < max; i++) {
Object next = array[i];
}
Any other things that should be considered have already been mentioned, so just my two cents (see ericksons post)
Greetz, GHad
To add on a bit to #Esteban Araya's answer, they will both require the creation of a new string each time through the loop (as the return value of the some Assignment expression). Those strings need to be garbage collected either way.
I know this is an old question, but I thought I'd add a bit that is slightly related.
I've noticed while browsing the Java source code that some methods, like String.contentEquals (duplicated below) makes redundant local variables that are merely copies of class variables. I believe that there was a comment somewhere, that implied that accessing local variables is faster than accessing class variables.
In this case "v1" and "v2" are seemingly unnecessary and could be eliminated to simplify the code, but were added to improve performance.
public boolean contentEquals(StringBuffer sb) {
synchronized(sb) {
if (count != sb.length())
return false;
char v1[] = value;
char v2[] = sb.getValue();
int i = offset;
int j = 0;
int n = count;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
}
return true;
}
It seems to me that we need more specification of the problem.
The
s = some Assignment;
is not specified as to what kind of assignment this is. If the assignment is
s = "" + i + "";
then a new sting needs to be allocated.
but if it is
s = some Constant;
s will merely point to the constants memory location, and thus the first version would be more memory efficient.
Seems i little silly to worry about to much optimization of a for loop for an interpreted lang IMHO.
When I'm using multiple threads (50+) then i found this to be a very effective way of handling ghost thread issues with not being able to close a process correctly ....if I'm wrong, please let me know why I'm wrong:
Process one;
BufferedInputStream two;
try{
one = Runtime.getRuntime().exec(command);
two = new BufferedInputStream(one.getInputStream());
}
}catch(e){
e.printstacktrace
}
finally{
//null to ensure they are erased
one = null;
two = null;
//nudge the gc
System.gc();
}