15

I read today a post about performance improvement in C# and Java.

I still stuck on this one:


19. Do not overuse instance variables

Performance can be improved by using local variables. The code in example 1 will execute faster than the code in Example 2.

Example1:

public void loop() {
    int j = 0;
    for ( int i = 0; i<250000;i++){
        j = j + 1;
    }
}

Example 2:

int i;
public void loop() {
    int j = 0;
    for (i = 0; i<250000;i++){
        j = j + 1;
    }
}

Indeed, I do not understand why it should be faster to instantiate some memory and release it every time a call to the loop function is done when I could do a simple access to a field.

It's pure curiosity, I'm not trying to put the variable 'i' in the class' scope :p Is that true that's faster to use local variables? Or maybe just in some case?

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
dotixx
  • 1,490
  • 12
  • 23
  • 2
    I think the performance difference would be negligible, you should be more concerned about developer performance in understanding the code. If you had a field or property that should be a local variable, I would be conflicted in understanding the purpose of it. If you want to know the performance difference, why not benchmark it (or read the IL that both generate)? – Matthew Jul 17 '13 at 15:12
  • 3
    Accessing the variable from the stack is probably faster than accessing it through a heap reference. – Sotirios Delimanolis Jul 17 '13 at 15:13
  • 2
    So much bad advice in that article I don't know where to start – Steve Kuo Jul 17 '13 at 15:28
  • 1
    @SteveKuo an answer might be a good place. – Matthew Jul 17 '13 at 15:34
  • Items 1, 3, 4, 5, 7, 16, 17, 18, 20 from the article are all bad advice. Much of it is outdated Java performance folklore. The author doesn't even stylize Java correctly (it's Java and not JAVA). – Steve Kuo Jul 17 '13 at 15:49
  • 6
    "Tips and tricks for performance lists" are in general worse than worthless: they are actively harmful because they encourage a bad approach to performance. Performance needs to be approached as an engineering discipline that uses carefully chosen metrics, customer-focused goals, empirical measurements and targeted fixes. Tips and tricks lists encourage micro-optimizations that do not actually benefit anyone and in many cases make performance worse. – Eric Lippert Jul 17 '13 at 15:54

6 Answers6

16
  1. Stack faster then Heap.

    void f()
    {
        int x = 123; // <- located in stack
    }
    
    int x; // <- located in heap
    void f()
    {
        x = 123  
    }
    
  2. Do not forget the principle of locality data. Local data should be better cached in CPU cache. If the data are close, they will loaded entirely into the CPU cache, and the CPU does not have to get them from memory.

svick
  • 236,525
  • 50
  • 385
  • 514
oakio
  • 1,868
  • 1
  • 14
  • 21
  • I think you're simplifying too much. Local variable can be actually located on the heap and a field can be located on the stack. – svick Jul 17 '13 at 19:12
  • If you have direct address then there is no difference is it in stack or heap. – Andrey Jul 17 '13 at 19:16
  • I agree, if you mean reference on object and structure with fields – oakio Jul 17 '13 at 19:21
8

The performance is down to the number of steps required to get the variable. Local variable addresses are known at compile time (they are a known offset on the stack), to access a member you load the object 'this' to get the address of the actual object, before you can get the address of the member variable.

StuPointerException
  • 7,117
  • 5
  • 29
  • 54
3

I tested a calculation with 500,000 iterations where I used about 20 variables locally and one that does it with fields. The local variable test was about 20 milliseconds and the one with fields was about 30 milliseconds. A significant performance gain when you use local variables.

Whether the performance difference is relevant, depends on the project. In your average business application the performance gain may not be noticeable and it is better to go for readable / maintainable code, but I am working on sound synthesis software where nano-optimizations like this actually become relevant.

jjvanzon
  • 51
  • 5
3

In C# another minor difference is the number of generated MSIL instructions (I guess it's similar in Java).

It takes two instructions to load an instance field:

ldarg.0                 // load "this" reference onto stack
ldfld   MyClass.myField // find the field and load its value

...but it only takes one instruction to load a local variable:

ldloc.0                 // load the value at index 0 from the list of local variables
Good Night Nerd Pride
  • 8,245
  • 4
  • 49
  • 65
2

Even if it will be, there will be almost non measurable difference in this cases. Probabbly in first case, there is some optimization done on processor registry level, but again:

  • it's almost irrelevant
  • and what is more important, often unpredictable.

In terms of memory, it's exactly the same, there is no any difference.

The first case it generaly better: as you declare variable there were it's imediately used, which is commonly used good pattern, as it's

  • easy to understand (scopes of responsibilities)
  • easy refactor
Tigran
  • 61,654
  • 8
  • 86
  • 123
  • 1
    The second example uses more memory when the method is not in execution, as that variable is always in memory for each instance of the class, regardless of whether the `loop` method gets called or not. – Matthew Jul 17 '13 at 15:19
  • @Matthew: all local variables declared in the method (used actually during current execution or not) are allocated and pushed on stack *by the way*. – Tigran Jul 17 '13 at 15:21
  • 1
    Yes, however that memory is freed when the `loop` method exits, but not in the case of example 2. – Matthew Jul 17 '13 at 15:22
  • @Mathew: wouldn't be so sure on this. It depends on microptimization that JIT *may* apply in corrent execution context. That's why the first case *in general* is a winner, as you don't relay on some *possible* optimizations and create a clean/readable/refactorable code. – Tigran Jul 17 '13 at 15:24
  • 1
    While I don't know all the possible optimizations the JIT might do, local variables have a shorter lifetime than fields. My concern is the statement that the memory usage is exactly the same sounds incorrect to me, conceptually fields and local variables are very different, not only their purpose, but their location in memory. – Matthew Jul 17 '13 at 15:31
  • @Matthew: try it out. In the function decalrea variable inside if(false){} and another time outside it. Check out both ILs. – Tigran Jul 17 '13 at 15:34
  • 1
    I understand that **while the function is executing** that both consume the same amount of memory, I am saying **when it's not being executed**, the first example consumes less memory. – Matthew Jul 17 '13 at 15:38
  • @Mathew: it does not consume any memory, if it's not executing. If you run the function, locals has to be allocated and them and arguments (at least) has to be pushed on stack. If there is no execution context, there is no memory pressure, there is no any locals allocation. – Tigran Jul 17 '13 at 15:40
  • 1
    Exactly, but the 2nd example, that memory for field `i` is always consumed so long as that class instance is in memory, not so for the first example, it is temporary for while the method `loop` is executing. – Matthew Jul 17 '13 at 15:44
1

I suspect there's very little difference, however in the case where the variable is a member of the object, each access requires an indirection via this (effectively), whereas the local variable does not.

More generally, the object has no need for a member i, it's only used in the context of the loop, so making it local to its use is better in any case.

SteveLove
  • 3,137
  • 15
  • 17