Use stack variables as much as possible

zhaozj2021-02-08  448

If you frequently access variables, you need to consider where you have access these variables. Is the variable be static variable or a stack variable, or an instance variable of a class? The storage location of the variable has a significant impact on the performance of the code to access it? For example, consider the following code:

Class StackVars

{

Private int instal;

Private static int staticvar;

// Access stack variable

Void StackAccess (int Val)

{

INT j = 0;

For (int i = 0; i

J = 1;

}

// Instance variables for access

Void Instance Access (Int Val)

{

For (int i = 0; i

INSTVAR = 1;

}

// Access the static variable

Void StaticAccess (Int Val)

{

For (int i = 0; i

Staticvar = 1;

}

}

Each method in this code performs the same loop and repeated the same number. The only difference is that each cycle increases a different type of variable. Method StackAccess increases a local stack variable, and instanceAccess increases one instance variable of the class, and StaticAccess is incremented by one STIC variable of the class.

InstanceAccess and StaticAccess execution time are basically the same. However, STACKACCESS is two to three times faster. Access stack variables are so fast because JVM access stack variables are less than it is performed by instance variables for it to access Static variables or classes. Take a look at the bytecode generated for these three methods:

Method void stackaccess (int)

0 iconst_0 // Press the 0 into the stack.

1 iStore_2 // Pop-up 0 and store it in the position of the index 2 in the partial variable table (J).

2 iconst_0 // is pressed into 0.

3 iStore_3 // Pop-up 0 and store it in a location (i) indexed in a local variable table (i).

4 GOTO 13 // Jump to position 13.

7 IINC 2 1 // will store J plus 1 at index 2.

10 IINC 3 1 // will store I plus 1 at index 3.

13 iLOAD_3 // Press the value (i) at the index 3.

14 iLOAD_1 // Press the value (VAL) at the index 1.

15 IF_ICMPLT 7 // Pop-up I and VAL. If i is less than VAL, jump to position 7.

18 RETURN // Returns the call method.

Method void instanceAccess (int)

0 iconst_0 // Press the 0 into the stack.

1 iStore_2 // Pop-up 0 and store it in a location (i) indexed in a local variable table (i).

2 goto 18 // Jump to position 18.

5 ALOAD_0 // Press Index 0 (this).

6 DUP // Copy the value of the stack top and press it.

7 getfield # 19

// Pop up the THIS object reference and pressed into the value of Instvar.

10 iconst_1 // Press 1.

11 Iadd // Pop up two values ​​of the top of the stack and press them.

12 Putfield # 19 // The two values ​​of the top of the stack will be popped and stored in the instvar.

15 IINC 2 1 // The i plus 1 of the index 2 is stored 1.

18 iLOAD_2 // Press the value (i) at the index 2.

19 ILOAD_1 / / Press the value (VAL) at the index 1.

20 IF_ICMPLT 5 // Pop-up I and VAL. If I is less than VAL, jump to position 5.

23 RETURN // Returns the call method.

Method void staticaccess (int)

0 iconst_0 // Press the 0 into the stack.

1 iStore_2 // Pop-up 0 and store it in a location (i) indexed in a local variable table (i).

2 goto 16 // Jump to position 16.

5 getStatic # 25

// Press the value of StaticVar in the constant storage pool into the stack.

8 iconst_1 // Press 1.

9 Iadd // Pop up two values ​​of the top and press them.

10 PutStatic # 25

// The pop-up and value are stored in StaticVar.

13 IINC 2 1 // The i plus 1 of the index 2 is stored 1.

16 iLOAD_2 // Press the value (i) at the index 2.

17 iLOAD_1 // Press the value (VAL) at the index 1.

18 IF_ICMPLT 5 // Pop-up I and VAL. If I is less than VAL, jump to position 5.

21 RETURN // Returns the call method.

Viewing the bytecode reveals a higher reason for the stack variable efficiency. JVM is a stack-based virtual machine, thus optimizing access and processing of stack data. All local variables are stored in a local variable table, process in the Java operand stack, and can be accessed efficiently. Access Static variables and instance variable costs, because JVM must use a higher cost code and access them from a constant storage pool. (The constant storage pool saves all types, fields, and methods used by the type.)

Typically, after the first time the STATIC variable or instance variable is accessed from the constant storage pool, the JVM will dynamically change the bytecode to use a higher efficiency. Despite this optimization, the access of the stack variable is still faster.

Considering these facts, you can re-build the previous code so that the operation is more efficient by accessing the stack variable rather than instance variables or STATIC variables. Consider the modified code:

Class StackVars

{

// The same as the previous ...

Void Instance Access (Int Val)

{

INT j = INSTVAR;

For (int i = 0; i

J = 1;

INSTVAR = J;

}

Void StaticAccess (Int Val)

{

Int j = staticvar;

For (int i = 0; i

J = 1;

Staticvar = j;

}

}

Method INSTANCEACCESS and STATICCCESS are modified to copy their instance variables or static variables into a local stack variable. When the processing of the variable is completed, its value is replicated back to the instance variable or the STATIC variable. This simple change significantly improves the performance of Instance Access and StaticACcess. The execution time of these three methods is now substantially the same, the implementation speed of instanceAccess and StaticACcess is only about 4% slower than the STACKACCESS execution speed. This does not mean that you should avoid using a Static variable or instance variable. You should use a storage mechanism that makes sense to your design. For example, if you access a STATIC variable or instance variable in a loop, you can temporarily store them in a local stack variable so that you can significantly increase the performance of the code. This will provide the most efficient bytecode instruction sequence for JVM execution.

转载请注明原文地址:https://www.9cbs.com/read-853.html

New Post(0)