局部变量和常量的性能分析

前两天群里有人问,下面的代码1 比代码2运行时间上慢了100ms,这是问什么? 请看下面的两个代码片段:

代码1

for(int i=0; i<Integer.MAX_VALUE; i++){
    sum+=i;
}

代码2

for(int i=0, len=Integer.MAX_VALUE; i<len; i++){
    sum+=i;
}

我本地使用的JDK1.8执行的,但每次执行这两段的时间基本一样。

下面代码是我执行的测试代码:

代码3

public class Test {
    public static void main(String[] args) {
        test1();
        test2();
    }
    public static int test1() {
        long start = System.currentTimeMillis();
        int sum = 0;
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            sum += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        return sum;
    }

    public static int test2() {
        long start = System.currentTimeMillis();
        int sum = 0;
        for (int i = 0, len = Integer.MAX_VALUE; i < len; i++) {
            sum += i;
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        return sum;
    }
}

Paste_Image.png

发现每次执行时间差不多,不会出现上述的差别的。我使用的JDK1.8。可能别的版本的JDK有此问题。

下面我又通过添加JVM编译模式参数运行程序得到如下结果:

-Xint:全部使用字节码解释运行 -Xcomp:全部被编译成机器码执行 -Xmixed: 使用混合编译,jdk1.8默认执行方式

Paste_Image.png

从执行结果我们发现 -Xcomp 和 -Xmixed模式:编译成本地机器码后执行的效率是一样的,没啥区别 -Xint模式:解释执行两个方法执行时间差距大概2秒

为什么-Xint模式下会有2秒的时间差距呢?

代码1和代码2的区别 代码1:在for循环中直接使用常量Integer.MAX_VALUE进行对比。 代码2:在定义一个len变量赋值为Integer.MAX_VALUE,在for循环中使用len局部变量进行对比。 区别一个引用的是全局常量,一个引用的是局部变量

局部变量存储在栈的局部变量表中 常量存储在方法区的常量池中(jdk1.7或之前叫方法区,jdk1.8叫元空间)

下面从字节码角度分析Test类中的test1方法和test2方法的局部变量表。

test1方法

从字节码从11到21之间是for循环体,可以看出19行ldc指令是每次都是从常量池中获取Integer.MAX_VALUE的值。

ldc指令说明

test2方法

字节码15-25之间是for循环,这个方法,我们可以看到在for循环外面先从常量池中获取Integer.MAX_VALUE的值赋值给本地变量,for循环体内每次进行比较的是本地变量,也就是局部变量表中的值,而不是每次从常量池获取变量的值。这就是test2方法比test1方法快的原因。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏性能与架构

mysql char与varchar类型的区别

image.png 基本区别 char 是固定长度的,varchar 是可变长度的 char 如果某个长度小于M,MySQL就会在它的右边用空格补足,使长度达到...

3355
来自专栏pangguoming

JS原型继承和类式继承

类式继承(构造函数) JS中其实是没有类的概念的,所谓的类也是模拟出来的。特别是当我们是用new 关键字的时候,就使得“类”的概念就越像其他语言中的类了。类式继...

4869
来自专栏星回的实验室

js重修课[四]:函数

函数有两种定义方法:定义表达式如var f = function(){};和声明语句如function f(){}。须知在变量提前这一现象中,声明语句可被提前,...

942
来自专栏IT可乐

Java关键字(四)——final

  对于Java中的 final 关键字,我们首先可以从字面意思上去理解,百度翻译显示如下:

913
来自专栏Java大联盟

Java基础之数组

1063
来自专栏深度学习思考者

一文搞懂C/C++中指针那些事(上篇)

一 指针变量 1.间接存取        指针变量的值为地址;普通变量的值为数据;其中“*”为指针运算符。&是地址操作符,用来引用一个内存地址。通过在变量名...

20810
来自专栏机器学习从入门到成神

C/C++学习之路(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

1002
来自专栏开源优测

[快学Python3]if条件控制

if语句 先看下Python中一般的条件控制语句的形式是怎么样的,如下所示: if 条件: # 代码块 elif 条件: ...

1984
来自专栏数据之美

python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域

在 python 中赋值语句总是建立对象的引用值,而不是复制对象。因此,python 变量更像是指针,而不是数据存储区域, ? 这点和大多数 OO 语言类似吧,...

2637
来自专栏十月梦想

JavaScript数组对象

万能操作 数组.splice(开始位置,数量,操作),操作后原数组的内容改变第一个参数是指定从几号位置开始删除或添加  第二个参数是指定删除几个元素

953

扫码关注云+社区

领取腾讯云代金券