使用临时变量提高Java代码性能
2013-03-13 09:34
676 查看
一个Java类中可以存在多种形式的变量,可以是最一般的成员变量;或将其定义为静态变量;也可以在方法中定义临时变量。这三种变量的存取效率如何?
1.测试
下面作个实验,看下面代码。
结果:
temp var: 350 milli seconds
instance var: 821 milli seconds
static var: 852 milli seconds
这段代码中的每个方法都执行相同的循环,并反复相同的次数。唯一的不同是每个循环使一个不同类型的变量递增。方法 tempAccess 使一个局部堆栈变量递增,instanceAccess 使类的一个成员实例变量递增,而 staticAccess 使类的一个 static 变量递增。
从结果中可以发现,instanceAccess 和 staticAccess 的执行时间基本相同。但是,tempAccess 要快两到三倍。
2.JVM存取变量机制
存取堆栈变量如此快是因为JVM 存取堆栈变量比它存取 static 变量或类的实例变量执行的操作少。
JVM 是一种基于堆栈的虚拟机,因此优化了对堆栈数据的存取和处理。所有局部变量都存储在一个局部变量表中,在 Java 操作数堆栈中进行处理,并可被高效地存取。
存取 static 变量和实例变量成本更高,因为 JVM 必须使用代价更高的操作码,并从常数存储池中存取它们。(常数存储池保存一个类型所使用的所有类型、字段和方法的符号引用。)通常,在第一次从常数存储池中访问 static 变量或实例变量以后,JVM 将动态更改字节码以使用效率更高的操作码。尽管有这种优化,堆栈变量的存取仍然更快。
3.优化代码
考虑到这些事实,就可以重新构建前面的代码,以便通过存取堆栈变量而不是实例变量或 static 变量使操作更高效。
结果:
temp var: 341 milli seconds
instance var: 370 milli seconds
static var: 361 milli seconds
方法 instanceAccess 和 staticAccess 被修改为将它们的实例变量或 static 变量复制到局部堆栈变量中。当变量的处理完成以后,其值又被复制回实例变量或 static 变量中。这种简单的更改明显提高了 instanceAccess 和 staticAccess 的性能。这三个方法的执行时间现在基本相同。
1.测试
下面作个实验,看下面代码。
class CheckVars { privateintinstVar;// 成员变量 privatestaticintstaticVar; // 静态变量 // 存取类方法中的临时变量 void tempAccess(int val) { int j = 0;// 临时变量 long startTime = System.currentTimeMillis(); for (int i = 0; i < val; i++) j += 1; long endTime = System.currentTimeMillis(); System.out.println("temp var: " + (endTime - startTime) + " milli seconds"); } // 存取类的成员变量 void instanceAccess(int val) { long startTime = System.currentTimeMillis(); for (int i = 0; i < val; i++) instVar += 1; long endTime = System.currentTimeMillis(); System.out.println("instance var: " + (endTime - startTime) + " milli seconds"); } // 存取类的 static 变量 void staticAccess(int val) { long startTime = System.currentTimeMillis(); for (int i = 0; i < val; i++) staticVar += 1; long endTime = System.currentTimeMillis(); System.out.println("static var: " + (endTime - startTime) + " milli seconds"); } publicstaticvoid main(String[] args){ CheckVars test=new CheckVars(); test.tempAccess(200000000); test.instanceAccess(200000000); test.staticAccess(200000000); } } |
temp var: 350 milli seconds
instance var: 821 milli seconds
static var: 852 milli seconds
这段代码中的每个方法都执行相同的循环,并反复相同的次数。唯一的不同是每个循环使一个不同类型的变量递增。方法 tempAccess 使一个局部堆栈变量递增,instanceAccess 使类的一个成员实例变量递增,而 staticAccess 使类的一个 static 变量递增。
从结果中可以发现,instanceAccess 和 staticAccess 的执行时间基本相同。但是,tempAccess 要快两到三倍。
2.JVM存取变量机制
存取堆栈变量如此快是因为JVM 存取堆栈变量比它存取 static 变量或类的实例变量执行的操作少。
JVM 是一种基于堆栈的虚拟机,因此优化了对堆栈数据的存取和处理。所有局部变量都存储在一个局部变量表中,在 Java 操作数堆栈中进行处理,并可被高效地存取。
存取 static 变量和实例变量成本更高,因为 JVM 必须使用代价更高的操作码,并从常数存储池中存取它们。(常数存储池保存一个类型所使用的所有类型、字段和方法的符号引用。)通常,在第一次从常数存储池中访问 static 变量或实例变量以后,JVM 将动态更改字节码以使用效率更高的操作码。尽管有这种优化,堆栈变量的存取仍然更快。
3.优化代码
考虑到这些事实,就可以重新构建前面的代码,以便通过存取堆栈变量而不是实例变量或 static 变量使操作更高效。
publicclass CheckVarsAdv { privateintinstVar; privatestaticintstaticVar; void tempAccess(int val) { int j = 0; long startTime = System.currentTimeMillis(); for (int i = 0; i < val; i++) j += 1; long endTime = System.currentTimeMillis(); System.out.println("temp var: " + (endTime - startTime) + " milli seconds"); } void instanceAccess(int val) { int j = instVar; long startTime = System.currentTimeMillis(); for (int i = 0; i < val; i++) j += 1; long endTime = System.currentTimeMillis(); System.out.println("instance var: " + (endTime - startTime) + " milli seconds"); instVar = j; } void staticAccess(int val) { int j = staticVar; long startTime = System.currentTimeMillis(); for (int i = 0; i < val; i++) j += 1; long endTime = System.currentTimeMillis(); System.out.println("static var: " + (endTime - startTime) + " milli seconds"); staticVar = j; } publicstaticvoid main(String[] args){ CheckVarsAdv test=new CheckVarsAdv(); test.tempAccess(200000000); test.instanceAccess(200000000); test.staticAccess(200000000); } } |
temp var: 341 milli seconds
instance var: 370 milli seconds
static var: 361 milli seconds
方法 instanceAccess 和 staticAccess 被修改为将它们的实例变量或 static 变量复制到局部堆栈变量中。当变量的处理完成以后,其值又被复制回实例变量或 static 变量中。这种简单的更改明显提高了 instanceAccess 和 staticAccess 的性能。这三个方法的执行时间现在基本相同。
相关文章推荐
- 使用临时变量提高Java代码性能 (转)
- 使用临时变量提高Java代码性能 (转)
- 提高你的Java代码质量吧:多使用异常,把性能问题放一边
- 提高你的Java代码质量吧:多使用异常,把性能问题放一边
- 多方面提高Java代码性能
- 提高你的Java代码质量吧:推荐在复杂字符串操作中使用正则表达式
- PayPal为什么从Java迁移到Node.js,性能提高一倍,文件代码减少44%
- 提高Java代码质量的Eclipse插件之Checkstyle的使用详解
- 使用java开发时该从哪些不同方面提高系统性能
- 提高你的Java代码质量吧:推荐使用String直接量赋值
- 使用Java代码获取服务器性能信息及局域网内主机名
- 使用 Cobertura 和反射机制提高 Java 单元测试中的代码覆盖率
- java里 使用apache-ant和cobertura测试代码覆盖率 环境变量配置
- 提高你的Java代码质量吧:你能正确使用String、StringBuffer、StringBuilder吗
- Java代码优化--尽可能地使用stack(栈)变量(方法内部的局部变量)
- 提高你的Java代码质量吧:频繁插入和删除时使用LinkedList
- Java代码质量改进之:使用ThreadLocal维护线程内部变量
- 在C++中使用Lambda函数提高代码性能