Performance Tips

1.In this document

  1. Avoid Creating Unnecessary Objects          避免多余的对象
  2. Prefer Static Over Virtual                多用static方法,它比其它方法快15%-20%
  3. Use Static Final For Constants               多用 static final 基本类型常量
  4. Avoid Internal Getters/Setters              在类内部避免使用getter,setter而直接使用成员
  5. Use Enhanced For Loop Syntax             遍历集合、数组时,用加强版的 for 语法
  6. Consider Package Instead of Private Access with Private Inner Classes 不必要不用内部类
  7. Avoid Using Floating-Point                 少用浮点数
  8. Know and Use the Libraries               解并使用库提供的优化代码
  9. Use Native Methods Carefully              小心使用native代码,它并不一定提升性能
  10. Use Native Methods Judiciously                官网也没有这个链接 这里
  11. Closing Notes                     官网也没有这个链接 这里
  12. Always Measure                    优化时要权衡

  This document primarily covers micro-optimizations that can improve overall app performance when combined, but it's unlikely that these changes will result in dramatic performance effects. Choosing the right algorithms and data structures should always be your priority, but is outside the scope of this document. You should use the tips in this document as general coding practices that you can incorporate into your habits for general code efficiency.

  There are two basic rules for writing efficient code:

 提升性能的两条原则:
  • Don't do work that you don't need to do.
  • Don't allocate memory if you can avoid it.

  One of the trickiest problems you'll face when micro-optimizing an Android app is that your app is certain to be running on multiple types of hardware. Different versions of the VM running on different processors running at different speeds. It's not even generally the case that you can simply say "device X is a factor F faster/slower than device Y", and scale your results from one device to others. In particular, measurement on the emulator tells you very little about performance on any device. There are also huge differences between devices with and without a JIT: the best code for a device with a JIT is not always the best code for a device without.

  To ensure your app performs well across a wide variety of devices, ensure your code is efficient at all levels and agressively optimize your performance.

2.避免多余的对象

  Avoid Creating Unnecessary Objects

  Object creation is never free. A generational garbage collector with per-thread allocation pools for temporary objects can make allocation cheaper, but allocating memory is always more expensive than not allocating memory.

  As you allocate more objects in your app, you will force a periodic garbage collection, creating little "hiccups" in the user experience. The concurrent garbage collector introduced in Android 2.3 helps, but unnecessary work should always be avoided.

  Thus, you should avoid creating object instances you don't need to. Some examples of things that can help:

  • If you have a method returning a string, and you know that its result will always be appended to a StringBuffer anyway, change your signature and implementation so that the function does the append directly, instead of creating a short-lived temporary object.

    返回一个临时对象追加到另一个对象,不如直接在该方法中追加。
  • When extracting strings from a set of input data, try to return a substring of the original data, instead of creating a copy. You will create a new String object, but it will share the char[] with the data. (The trade-off being that if you're only using a small part of the original input, you'll be keeping it all around in memory anyway if you go this route.)
    返回子串,不返回一个内容与子串相同新串。

  A somewhat more radical idea is to slice up multidimensional arrays into parallel single one-dimension arrays:

 用多个一维的数组代替多维数组。
  • An array of ints is a much better than an array of Integer objects, but this also generalizes to the fact that two parallel arrays of ints are also a lot more efficient than an array of (int,int) objects. The same goes for any combination of primitive types.

    Array<int> 比 Array<Integer>好。多个Array<int>比一个Array<Object>好,其中Object包含两个int成员。
    其它基本类型同理。
  • If you need to implement a container that stores tuples of (Foo,Bar) objects, try to remember that two parallel Foo[] and Bar[] arrays are generally much better than a single array of custom (Foo,Bar)objects. (The exception to this, of course, is when you're designing an API for other code to access. In those cases, it's usually better to make a small compromise to the speed in order to achieve a good API design. But in your own internal code, you should try and be as efficient as possible.)
    假设类Obj含Foo,Bar,用两个数组Foo[]+Bar[]比 一个Obj[] 好。

  Generally speaking, avoid creating short-term temporary objects if you can. Fewer objects created mean less-frequent garbage collection, which has a direct impact on user experience.

 通常来说,就尽量避免产生临时对象。对象少,gc就少。用户体验就好。

3.多用static方法,它比其它方法快15%-20%

  Prefer Static Over Virtual 

  If you don't need to access an object's fields, make your method static. Invocations will be about 15%-20% faster. It's also good practice, because you can tell from the method signature that calling the method can't alter the object's state.

4.多用 static final 基本类型常量

  Use Static Final For Constants 

  Consider the following declaration at the top of a class:

 static int intVal = ;
static String strVal = "Hello, world!";

  The compiler generates a class initializer method, called <clinit>, that is executed when the class is first used. The method stores the value 42 into intVal, and extracts a reference from the classfile string constant table for strVal. When these values are referenced later on, they are accessed with field lookups.

  We can improve matters with the "final" keyword:

 static final int intVal = ;
static final String strVal = "Hello, world!";

  The class no longer requires a <clinit> method, because the constants go into static field initializers in the dex file. Code that refers to intVal will use the integer value 42 directly, and accesses to strVal will use a relatively inexpensive "string constant" instruction instead of a field lookup.

使用static final 常量时,不用调用 <clinit>方法,访问时也不用从类中找,它直接定义在 .dex 文件中。这样它就比非final的快很多。
注意:只支持基本类型和String类型。其它Object类型的不支持。

  Note: This optimization applies only to primitive types and String constants, not arbitrary reference types. Still, it's good practice to declare constants static final whenever possible.

5.在类内部避免使用getter,setter而直接使用成员

  Avoid Internal Getters/Setters

  In native languages like C++ it's common practice to use getters (i = getCount()) instead of accessing the field directly (i = mCount). This is an excellent habit for C++ and is often practiced in other object oriented languages like C# and Java, because the compiler can usually inline the access, and if you need to restrict or debug field access you can add the code at any time.

  However, this is a bad idea on Android. Virtual method calls are expensive, much more so than instance field lookups. It's reasonable to follow common object-oriented programming practices and have getters and setters in the public interface, but within a class you should always access fields directly.

  Without a JIT, direct field access is about 3x faster than invoking a trivial getter. With the JIT (where direct field access is as cheap as accessing a local), direct field access is about 7x faster than invoking a trivial getter.

 在android上,virtual 方法非常费时,在类内部直接使用成员比用getter,setter更好。未使用JIT编译,直接使用比用getter快3倍,使用JIT时,快7倍。

  Note that if you're using ProGuard, you can have the best of both worlds because ProGuard can inline accessors for you.

6.遍历集合、数组时,用加强版的 for 语法

  Use Enhanced For Loop Syntax

  The enhanced for loop (also sometimes known as "for-each" loop) can be used for collections that implement the Iterable interface and for arrays. With collections, an iterator is allocated to make interface calls to hasNext() and next(). With an ArrayList, a hand-written counted loop is about 3x faster (with or without JIT), but for other collections the enhanced for loop syntax will be exactly equivalent to explicit iterator usage.

  There are several alternatives for iterating through an array:

 static class Foo {
int mSplat;
} Foo[] mArray = ... public void zero() {
int sum = ;
for (int i = ; i < mArray.length; ++i) {
sum += mArray[i].mSplat;
}
} public void one() {
int sum = ;
Foo[] localArray = mArray;
int len = localArray.length; for (int i = ; i < len; ++i) {
sum += localArray[i].mSplat;
}
} public void two() {
int sum = ;
for (Foo a : mArray) {
sum += a.mSplat;
}
}

  zero() is slowest, because the JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop.

  one() is faster. It pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit.

  two() is fastest for devices without a JIT, and indistinguishable from one() for devices with a JIT. It uses the enhanced for loop syntax introduced in version 1.5 of the Java programming language.

  So, you should use the enhanced for loop by default, but consider a hand-written counted loop for performance-critical ArrayList iteration.

 当没使用JIT时,two()最快,one()次之,zero()最差。开了JIT之后,two,one一样。
 所以要多用加强版的 for 语法。

  Tip: Also see Josh Bloch's Effective Java, item 46.

7.不必要不用内部类

  Consider Package Instead of Private Access with Private Inner Classes 

  Consider the following class definition:

 public class Foo {
private class Inner {
void stuff() {
Foo.this.doStuff(Foo.this.mValue);
}
} private int mValue; public void run() {
Inner in = new Inner();
mValue = ;
in.stuff();
} private void doStuff(int value) {
System.out.println("Value is " + value);
}
}

  What's important here is that we define a private inner class (Foo$Inner) that directly accesses a private method and a private instance field in the outer class. This is legal, and the code prints "Value is 27" as expected.

  The problem is that the VM considers direct access to Foo's private members from Foo$Inner to be illegal because Foo and Foo$Inner are different classes, even though the Java language allows an inner class to access an outer class' private members. To bridge the gap, the compiler generates a couple of synthetic methods:

 尽管java支持内部类访问外部类的私有成员,但是通过提供了相关静态访问方法实现的。这些方法会降低性能。如下两个方法:
 /*package*/ static int Foo.access$(Foo foo) {
return foo.mValue;
}
/*package*/ static void Foo.access$(Foo foo, int value) {
foo.doStuff(value);
}

  The inner class code calls these static methods whenever it needs to access the mValue field or invoke the doStuff() method in the outer class. What this means is that the code above really boils down to a case where you're accessing member fields through accessor methods. Earlier we talked about how accessors are slower than direct field accesses, so this is an example of a certain language idiom resulting in an "invisible" performance hit.

  If you're using code like this in a performance hotspot, you can avoid the overhead by declaring fields and methods accessed by inner classes to have package access, rather than private access. Unfortunately this means the fields can be accessed directly by other classes in the same package, so you shouldn't use this in public API.

 解决方案:如果不介意该成员被同包下的其它类访问。

8.少用浮点数

  Avoid Using Floating-Point 

  As a rule of thumb, floating-point is about 2x slower than integer on Android-powered devices.

 在android设备上,float要比integer慢两倍。

  In speed terms, there's no difference between float and double on the more modern hardware. Space-wise,double is 2x larger. As with desktop machines, assuming space isn't an issue, you should prefer double to float.

  Also, even for integers, some processors have hardware multiply but lack hardware divide. In such cases, integer division and modulus operations are performed in software—something to think about if you're designing a hash table or doing lots of math.

9.了解并使用库提供的优化代码

  Know and Use the Libraries 

  In addition to all the usual reasons to prefer library code over rolling your own, bear in mind that the system is at liberty to replace calls to library methods with hand-coded assembler, which may be better than the best code the JIT can produce for the equivalent Java. The typical example here is String.indexOf() and related APIs, which Dalvik replaces with an inlined intrinsic. Similarly, the System.arraycopy() method is about 9x faster than a hand-coded loop on a Nexus One with the JIT.

 了解并使用那些库提供的比优化版代码,在Dalvik上, String.indexOf()System.arraycopy() 比用JIT编译的手写循环快9倍。

  Tip: Also see Josh Bloch's Effective Java, item 47.

10.小心使用native代码,它并不一定提升性能

  Use Native Methods Carefully 

  Developing your app with native code using the Android NDK isn't necessarily more efficient than programming with the Java language. For one thing, there's a cost associated with the Java-native transition, and the JIT can't optimize across these boundaries. If you're allocating native resources (memory on the native heap, file descriptors, or whatever), it can be significantly more difficult to arrange timely collection of these resources. You also need to compile your code for each architecture you wish to run on (rather than rely on it having a JIT). You may even have to compile multiple versions for what you consider the same architecture: native code compiled for the ARM processor in the G1 can't take full advantage of the ARM in the Nexus One, and code compiled for the ARM in the Nexus One won't run on the ARM in the G1.

 本地代码最初是为了移植其它项目而设计,并不是使用本地代码就一定能提升性能。本地代码可能要为不同的设备编译不同的版本。

  Native code is primarily useful when you have an existing native codebase that you want to port to Android, not for "speeding up" parts of your Android app written with the Java language.

  If you do need to use native code, you should read our JNI Tips.

  Tip: Also see Josh Bloch's Effective Java, item 54.

11.JIT的神话

  Performance Myths 

  On devices without a JIT, it is true that invoking methods via a variable with an exact type rather than an interface is slightly more efficient. (So, for example, it was cheaper to invoke methods on a HashMap map than a Map map, even though in both cases the map was a HashMap.) It was not the case that this was 2x slower; the actual difference was more like 6% slower. Furthermore, the JIT makes the two effectively indistinguishable.

 在没有使用JIT编译时,使用基类引用不如使用具体类型引用高效。前者比后者慢6%,然而使用JIT后,区别很小。

  On devices without a JIT, caching field accesses is about 20% faster than repeatedly accessing the field. With a JIT, field access costs about the same as local access, so this isn't a worthwhile optimization unless you feel it makes your code easier to read. (This is true of final, static, and static final fields too.)

 没有使用JIT编译时,缓存属性比每次都直接访问快20%,但是使用JIT后就可以不用这么做了。

13.优化时要权衡

  Always Measure 

  Before you start optimizing, make sure you have a problem that you need to solve. Make sure you can accurately measure your existing performance, or you won't be able to measure the benefit of the alternatives you try.

 优化时要权衡,确定有问题,并可优化才去行动。

  Every claim made in this document is backed up by a benchmark. The source to these benchmarks can be found in the code.google.com "dalvik" project.

  The benchmarks are built with the Caliper microbenchmarking framework for Java. Microbenchmarks are hard to get right, so Caliper goes out of its way to do the hard work for you, and even detect some cases where you're not measuring what you think you're measuring (because, say, the VM has managed to optimize all your code away). We highly recommend you use Caliper to run your own microbenchmarks.

  You may also find Traceview useful for profiling, but it's important to realize that it currently disables the JIT, which may cause it to misattribute time to code that the JIT may be able to win back. It's especially important after making changes suggested by Traceview data to ensure that the resulting code actually runs faster when run without Traceview.

 Traceview 并不显示JIT。

  For more help profiling and debugging your apps, see the following documents:

Android 性能优化(19)*代码优化11条技巧:Performance Tips的更多相关文章

  1. Android性能优化典范(二)

    Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...

  2. android app性能优化大汇总(google官方Android性能优化典范 - 第2季)

    Google前几天刚发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的 ...

  3. Android性能优化典范 - 第2季

    Google发布了Android性能优化典范第2季的课程,一共20个短视频,包括的内容大致有:电量优化,网络优化,Wear上如何做优化,使用对象池来提高效率,LRU Cache,Bitmap的缩放,缓 ...

  4. Android 性能优化探究

    使用ViewStub动态载入布局.避免一些不常常的视图长期握住引用: ViewStub的一些特点: 1. ViewStub仅仅能Inflate一次,之后ViewStub对象被置空:某个被ViewStu ...

  5. MYSQL性能优化的最佳20+条经验

    MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论  131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...

  6. 使用ThinkPHP开发中MySQL性能优化的最佳21条经验

    使用ThinkPHP开发中MySQL性能优化的最佳21条经验讲解,目前,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更 ...

  7. Android群英传笔记——第十章:Android性能优化

    Android群英传笔记--第十章:Android性能优化 随着Android应用增多,功能越来越复杂,布局也越来越丰富了,而这些也成为了阻碍一个应用流畅运行,因此,对复杂的功能进行性能优化是创造高质 ...

  8. android 性能优化

    本章介绍android高级开发中,对于性能方面的处理.主要包括电量,视图,内存三个性能方面的知识点. 1.视图性能 (1)Overdraw简介 Overdraw就是过度绘制,是指在一帧的时间内(16. ...

  9. Android性能优化典范第一季

    2015年伊始,Google发布了关于Android性能优化典范的专题,一共16个短视频,每个3-5分钟,帮助开发者创建更快更优秀的Android App.课程专题不仅仅介绍了Android系统中有关 ...

随机推荐

  1. hdu - 2266 How Many Equations Can You Find (简单dfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=2266 给一个字符串和一个数n,在字符串中间可以插入+或者 -,问有多少种等于n的情况. 要注意任意两个数之间都可 ...

  2. codevs——2750 心系南方灾区

    2750 心系南方灾区  时间限制: 1 s  空间限制: 2000 KB  题目等级 : 青铜 Bronze 题解  查看运行结果     题目描述 Description 现在我国南方正在承受百年 ...

  3. codevs——2147 数星星

    2147 数星星  时间限制: 3 s  空间限制: 64000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 小明是一名天文爱好者,他喜欢晚上看星星 ...

  4. select语句中会影响查询效率的因素

    1.没有创建索引,或者没有正确使用索引;2.存在死锁的情况,从而导致select语句挂起; 3.返回不必要的列,如很多人喜欢在程序中使用select * from 这样会查询表或视图中的所有字段,如果 ...

  5. 【nginx】nginx与apache的优缺点比较

    参考: http://zyan.cc/nginx_php_v6/ nginx相对于apache的优点: 1.轻量级,同样的web 服务,比apache服务器占用更少的内存及资源 2.抗并发,nginx ...

  6. WebLogic(12C)——简单公布和JDBC

    一,简单公布应用 1.点击"安装".開始部署应用: 2,找到要部署的项目路径: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGFue ...

  7. 【C语言】推断一个数是否为2的n次方

    //推断一个数是否为2的n次方 #include <stdio.h> int is_two_n(int num) { if ((num&(num - 1))) //去掉一个1,推断 ...

  8. Mariadb 事务

    事务 事务具有ACID特性:原子性(A,atomicity).一致性(C,consistency).隔离性(I,isolation).持久性(D,durabulity). 1.原子性:事务内的所有操作 ...

  9. 字符串处理(正则表达式、NSScanner扫描、CoreParse解析器)-b

    搜索 在一个字符串中搜索子字符串 最灵活的方法 1 - (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptio ...

  10. MYSQL入库常用PHP函数

    addslashes   addslashes() 函数在指定的预定义字符前添加反斜杠.这些字符是单引号(').双引号(").反斜线(\)与NUL(NULL字符).   stripslash ...