首页 > 编程知识 正文

android稳定性性能(android系统流畅度排行)

时间:2023-05-06 11:16:25 阅读:74599 作者:2585

移开眼睛,拿着耳机,听听看~!

今天,我将简要介绍在android中使用trycatch语句是否会影响性能。

我在网上查了资料,发现有些for循环中有trycatch语句,循环中一直担心执行trycatch语句会影响效率,以后不会影响性能。 请在这里记录。

1、将JAVA性能调整try/catch块移出循环

据说将try/catch阻滞进入循环体内,会严重影响性能。 因为使用try/catch模块会让JAVA虚拟机执行许多额外的工作。 谁都说:“嗨,哥哥,路上可能有蛇。 于是,听到的人只能手里拿着木棍,小心翼翼地往前走。”

将try/catch阻滞推出循环之外,是对很多人说:“嗨,兄弟们,路上可能有蛇。 于是听到的人安排一些人拿着木棍往前走,其他人几乎不受影响。”

这个理论很好。 在测试中对性能的实际影响

2、循环条件下匹配try/catch块的源代码

package com.java.test;

import java.util.ArrayList;

import java.util.List;

//*

*使用预热模式JVM参数:-xx :打印完成

*目标:测试在周期中使用try/catch对性能的影响

*

*/

公共类体系结构测试{

ListaList=new ArrayList (;

publicstaticvoidmain (字符串[ ] args ) throws Exception { )。

intwarmUpCycles=10000000; //预热次数

inttestCycles=50000000; //正式执行次数

easytrycatchtestse=neweasytrycatchtest (;

system.out.println (.预热循环开始. );

longcatchtime=se.runcatchloop (warmup cycles;

longnotcatchtime=se.runcatchnotloop (波纹周期;

system.out.println(……预热结束);

system.out.println(……预热阶段,try/catch在循环期间为:(catchtime );

system.out.println(……在预热阶段,try/catch循环: (通告程序);

system.out.println (.进入正式周期. );

catch time=se.runcatchloop (test cycles );

notcatchtime=se.runcatchnotloop (test cycles );

system.out.println(……正式运行阶段,try/catch周期为:(catchtime );

system.out.println(……在正式运营阶段,try/catch周期为:(notcatchtime );

}

publicEasyTryCatchTest (

alist.add('0);

}

//try/catch是具体的循环体(内环循环)

隐私保护语言(Int iterations ) {

//启动计时器

longstartTime=System.nanoTime (;

for(intloop=0; loop iterations; loop ()。

try {

stringtemp=alist.get(0;

}catch(exceptione ) }

}

//计时器完成

longelapsedtime=system.nano time (;

保留时间-开始时间(return );

}

//try/catch不在具体循环体(内环循环)中

公共语言连接(int iterations ) {

//启动计时器

longstartTime=System.nanoTime (;

try {

for(intloop=0; loop iterations; loop ()。

stringtemp=alist.get(0;

}

} catch(Exception e) {}

// 计时完成

longelapsedTime = System.nanoTime();

return(elapsedTime - startTime);

}

}

3、运行结果

…预热循环开始 …

…预热结束

…预热阶段,try/catch在循环中耗时: 76507316

…预热阶段,try/catch不在循环中耗时: 76292613

…进入正式循环 …

…正式运行阶段,try/catch在循环中耗时: 389151690

…正式运行阶段,try/catch不在循环中耗时: 389874615

4、结论

从测试结果来看,可能我们的JDK(1.6)会自动优化字节码的缘故,因此try/catch是否在循环中,对整体性能的影响几乎微乎其微,389151690 389874615 差距非常的小。

以上是没有发生异常的情况,如果发生异常,那么也就无法比较了。

这里再举一个例子:

讨论的问题

当时讨论的是这样的问题:

比较下面两种try catch写法,哪一种性能更好。

for (int i = 0; i < 1000000; i++) {

try {

Math.sin(j);

} catch (Exception e) {

e.printStackTrace();

}

}

try {

for (int i = 0; i < 1000000; i++) {

Math.sin(j);

}

} catch (Exception e) {

e.printStackTrace();

}

结论

在没有发生异常时,两者性能上没有差异。如果发生异常,两者的处理逻辑不一样,已经不具有比较的意义了。

分析

要知道这两者的区别,最好的办法就是查看编译后生成的Java字节码。看一下try catch到底做了什么。

下面是我的测试代码

import org.openjdk.jmh.annotations.Benchmark;

/**

* Created by pcdlc on 16-7-10.

*/

public class ForTryAndTryFor {

public static void main(String[] args) {

tryFor();

forTry();

}

public static void tryFor() {

int j = 3;

try {

for (int i = 0; i < 1000; i++) {

Math.sin(j);

}

} catch (Exception e) {

e.printStackTrace();

}

}

public static void forTry() {

int j = 3;

for (int i = 0; i < 1000; i++) {

try {

Math.sin(j);

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

使用javap -c fileName.class输出对应的字节码

Compiled from "ForTryAndTryFor.java"

public class com.pcdlc.java.performancetTest.ForTryAndTryFor {

public com.pcdlc.java.performancetTest.ForTryAndTryFor();

Code:

0: aload_0

1: invokespecial #1 // Method java/lang/Object."":()V

4: return

public static void main(java.lang.String[]);

Code:

0: invokestatic #2 // Method tryFor:()V

3: invokestatic #3 // Method forTry:()V

6: return

public static void tryFor();

Code:

0: iconst_3

1: istore_0

2: iconst_0

3: istore_1

4: iload_1

5: sipush 1000

8: if_icmpge 23

11: iload_0

12: i2d

13: invokestatic #4 // Method java/lang/Math.sin:(D)D

16: pop2

17: iinc 1, 1

20: goto 4

23: goto 31

26: astore_1

27: aload_1

28: invokevirtual #6 // Method java/lang/Exception.printStackTrace:()V

31: return

Exception table:

from to target type

2 23 26 Class java/lang/Exception

public static void forTry();

Code:

0: iconst_3

1: istore_0

2: iconst_0

3: istore_1

4: iload_1

5: sipush 1000

8: if_icmpge 31

11: iload_0

12: i2d

13: invokestatic #4 // Method java/lang/Math.sin:(D)D

16: pop2

17: goto 25

20: astore_2

21: aload_2

22: invokevirtual #6 // Method java/lang/Exception.printStackTrace:()V

25: iinc 1, 1

28: goto 4

31: return

Exception table:

from to target type

11 17 20 Class java/lang/Exception

}

指令含义不是本文的重点,所以这里就不介绍具体的含义,感兴趣可以到Oracle官网查看相应指令的含义The Java Virtual

Machine Instruction Set

好了让我们来关注一下try catch 到底做了什么。我们就拿forTry方法来说吧,从输出看,字节码分两部分,code(指令)和exception table(异常表)两部分。当将java源码编译成相应的字节码的时候,如果方法内有try catch异常处理,就会产生与该方法相关联的异常表,也就是Exception table:部分。异常表记录的是try

起点和终点,catch方法体所在的位置,以及声明捕获的异常种类。通过这些信息,当程序出现异常时,java虚拟机就会查找方法对应的异常表,如果发现有声明的异常与抛出的异常类型匹配就会跳转到catch处执行相应的逻辑,如果没有匹配成功,就会回到上层调用方法中继续查找,如此反复,一直到异常被处理为止,或者停止进程。具体介绍可以看这篇文章How

the Java virtual machine handles exceptions

所以,try 在反映到字节码上的就是产生一张异常表,只有发生异常时才会被使用。由此得到出开始的结论。

这里再对结论扩充:

try catch与未使用try catch代码区别在于,前者禁止try语句块中的代码进行优化,例如重排序,try catch里面的代码是不会被编译器优化重排的。对于上面两个函数而言,只是异常表中try起点和终点位置不一样。至于刚刚说到的指令重排的问题,由于for循环条件部分符合happens- before原则,因此两者的for循环都不会发生重排。当然只是针对这里而言,在实际编程中,还是提倡try

catch范围尽量小,这样才可以充分发挥java编译器的优化能力。

至于网上得出的for-try比try-catch要快是由于cpu执行代码时可能有环境的影响因素,因为手机可能同时执行其他线程,所以测试的时间不准确。具体来说:

原因至少有下面这些:System.currentTimeMillis()测量的只是逝去的时间,并没有反映出cpu执行该函数真正消耗的时间。

这导致线程未被分配cpu资源时,等待cpu的时间也会被计算进去

JIT优化导致结果出现偏差。

像这种多次循环非常容易触发JIT的优化机制,关于JIT,这里简短的介绍一下

在Java编程语言和环境中,即时编译器(JIT compiler,just-in-time compiler)是一个把Java的字节码(包括需要被解释的指令的程序)转换成可以直接发送给处理器的指令的程序。烂漫的火写好一个Java程序后,源语言的语句将由Java编译器编译成字节码,而不是编译成与某个特定的处理器硬件平台对应的指令代码(比如,Intel的Pentium微处理器或IBM的System/390处理器)。字节码是可以发送给任何平台并且能在那个平台上运行的独立于平台的代码。

简单来说,JIT会将某些符合条件(比如,频繁的循环)的字节码被编译成目标的机器指令直接执行,从而加快执行速度。可以通过配置-XX:+PrintCompilation参数,观察JIT。当JIT执行优化时,会在终端输出相应的优化信息。

类加载时间也被统计进来了。

类首次被使用时,会触发类加载,产生了时间消耗。

由上面的分析不难看出为什么绝大多数时候tryFor会比forTry快了,JIT编译耗时和类加载时间会被统计到第一个执行的函数forTry里面。要验证这个也非常简单,把两个函数的调用顺序互换,然后再进行测试。

当然,还有一点不能忽略的是System.currentTimeMillis()并不是统计cpu真正执行时间,所以可能测试的结果会有出入。可以使用JProfiler配合Intellij IDEA进行测试,下面会提到。由于这些因素影响着测试结果,从而使得测试结果扑朔迷离

所以总结一下,在没有异常时,try-catch不影响性能,当发生异常时,才会有多余的消耗。

android try catch并不影响性能就讲完了。

就这么简单。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。