局部变量竟然比全局变量快 5 倍?(下)

简介: 局部变量竟然比全局变量快 5 倍?

局部变量为什么快?


要理解为什么局部变量会比全局变量快这个问题,我们只需要使用 javac 把他们编译成字节码就可以找到原因了,编译的字节码如下:


javap -c VarOptimize
警告: 文件 ./VarOptimize.class 不包含类 VarOptimize
Compiled from "VarOptimize.java"
public class com.example.optimize.VarOptimize {
  char[] myChars;
  public com.example.optimize.VarOptimize();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: ldc           #7                  // String Oracle Cloud Infrastructure Low data networking fees and automated migration Oracle Cloud Infrastructure platform is built for enterprises that are looking for higher performance computing with easy migration of their on-premises applications to the Cloud.
       7: invokevirtual #9                  // Method java/lang/String.toCharArray:()[C
      10: putfield      #15                 // Field myChars:[C
      13: return
  public static void main(java.lang.String[]);
    Code:
       0: new           #16                 // class com/example/optimize/VarOptimize
       3: dup
       4: invokespecial #21                 // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #22                 // Method globalVarTest:()V
      12: aload_1
      13: invokevirtual #25                 // Method localityVarTest:()V
      16: return
  public void globalVarTest();
    Code:
       0: iconst_0
       1: istore_1
       2: iconst_0
       3: istore_2
       4: iload_2
       5: aload_0
       6: getfield      #15                 // Field myChars:[C
       9: arraylength
      10: if_icmpge     33
      13: aload_0
      14: getfield      #15                 // Field myChars:[C
      17: iload_2
      18: caload
      19: bipush        99
      21: if_icmpne     27
      24: iinc          1, 1
      27: iinc          2, 1
      30: goto          4
      33: return
  public void localityVarTest();
    Code:
       0: aload_0
       1: getfield      #15                 // Field myChars:[C
       4: astore_1
       5: iconst_0
       6: istore_2
       7: iconst_0
       8: istore_3
       9: iload_3
      10: aload_1
      11: arraylength
      12: if_icmpge     32
      15: aload_1
      16: iload_3
      17: caload
      18: bipush        99
      20: if_icmpne     26
      23: iinc          2, 1
      26: iinc          3, 1
      29: goto          9
      32: return
}


其中关键的信息就在 getfield 关键字上,getfield 在此处的语义是从堆上获取变量,从上述的字节码可以看出 globalVarTest 方法在循环的内部每次都通过 getfield 关键字从堆上获取变量,而 localityVarTest 方法并没有使用 getfield 关键字,而是使用了出栈操作来进行业务处理,而从堆中获取变量比出栈操作要慢很多,因此使用全局变量会比局部变量慢很多。关于堆、栈的内容关注公众号「Java中文社群」我在后面的 JVM 优化的章节会单独讲解。


关于缓存


有人可能会说无所谓,反正使用全局变量会使用 CPU Cache,这样性能也和局部变量差不多,那我就随便用吧,反正也差不多。


但磊哥的建议是,能用局部变量的绝不使用全局变量,因为 CPU 缓存有以下 3 个问题:


  1. CPU Cache 采用的是 LRU 和 Random 的清除算法,不常使用的缓存和随机抽取一部分缓存会被删除掉,如果正好是你用的那个全局变量呢?
  2. CPU Cache 有缓存命中率的问题,也就是有一定的几率会访问不到缓存;
  3. 部分 CPU 只有两级缓存(L1 和 L2),因此可以使用的空间是有限的。


综上所述,我们不能把程序的执行性能完全托付给一个不那么稳定的系统硬件,所以能用局部变量坚决不要使用全局变量


关键点:编写适合你的代码,在性能、可读性和实用性之间,找到属于你的平衡点!


总结


本文我们讲了局部变量的和全局变量的区别,如果使用全局变量会用 getfield 关键字从堆中获取变量,而局部变量则是通过出栈来获取变量的,因为出栈操作要比堆操作快很多,因此局部变量操作也会比全局变量快很多,所以建议你使用局部变量而不是全局变量。

相关文章
|
2月前
初始化局部变量和全局变量
【10月更文挑战第3天】初始化局部变量和全局变量。
38 5
|
4月前
|
存储
全局变量和局部变量在堆和栈的区别
全局变量和局部变量在堆和栈的区别
475 0
|
存储 C语言 Perl
西门子S7-1200的变量如何使用?什么是局部变量和全局变量?临时变量和静态变量有什么区别?
今天给大家讲一下什么是局部变量、全局变量、临时变量、静态变量,这些变量都有什么区别,以及在西门子S7-1200中这些变量如何来使用。
西门子S7-1200的变量如何使用?什么是局部变量和全局变量?临时变量和静态变量有什么区别?
|
C++
39.【C/C++ 全局变量和局部变量 (详解)】
39.【C/C++ 全局变量和局部变量 (详解)】
88 0
|
存储 C语言 C++
函数的内部处理及全局变量和局部变量
函数的内部处理及全局变量和局部变量
129 0
函数的内部处理及全局变量和局部变量
|
存储
全局变量和局部变量
全局变量和局部变量
82 0
|
存储 数据可视化 小程序
在函数中使用局部变量并且通过局部变量返回函数值的方案来了
感谢小游戏可视化体验官群中的一位叫做“@天羽地王”的朋友提供的思路。本文内容主要包括如何在函数中使用局部变量并且通过局部变量来返回函数的结果值。 如果你没有任何的游戏开发经验,欢迎阅读我的“人人都能做游戏”系列教程,它会手把手的教你做出自己的第一个小游戏。
94 0
|
C++
【C++】局部变量和全局变量
有关C++局部变量和全局变量的记录
137 0
【C++】局部变量和全局变量
|
Java 编译器
成员变量和局部变量在内存中的变化
今天我们从成员变量和局部变量来加深印象,彻底弄懂成员变量和局部变量在内存中的变化
262 2
成员变量和局部变量在内存中的变化