我可以从Dalvik和Android工具链中得到什么样的优化?

Tho*_*mas 67 java optimization android dalvik

我正在开发一个高性能的Android应用程序(游戏),尽管我首先尝试编写可读性代码,但我想在脑海中留下一个关于幕后发生的事情的图片.使用C++,我已经对编译器将为我做什么和不做什么做了很好的直觉.我正在尝试为Java/Android做同样的事情.

因此这个问题.我在网上找不到这个话题.Java编译器,Dalvik转换器(dx)和/或JITter(在Android 2.2+上)是否会执行如下优化?

  • 方法内联.在什么条件下?private方法总是可以安全地内联; 这样做会吗?public final方法怎么样?关于其他类对象的方法?static方法?如果编译器可以轻松推导出对象的运行时类型,该怎么办?我要声明的方法finalstatic在可能的情况?

  • 常见的子表达式消除.例如,如果我访问someObject.someField两次,查找只会进行一次吗?如果它是对吸气剂的召唤怎么办?如果我使用一些算术表达式两次会怎么样 它只会被评估一次吗?如果我使用某些表达式的结果,我知道它的值不会改变,作为for循环的上限,该怎么办?

  • 检查数组查找的边界.工具链是否会在某些条件下消除这种情况,例如原型for循环?

  • 价值内联.访问一些public static final int总是内联?即使他们在另一个班级?即使他们在另一个包裹?

  • 分支预测.这甚至有多大问题?是否会在典型的Android设备上大幅提升性能?

  • 简单算术.将someInt * 2被取代someInt << 1

诸如此类......

Ben*_*Ben 104

这是Ben,JIT @ Google的工程师之一.当Bill和我开始这个项目时,我们的目标是尽快提供一个有效的JIT,对资源争用的影响最小(例如内存占用,CPU被编译器线程劫持),这样它就可以在低端设备上运行好.因此我们使用了非常原始的基于轨迹的模型.也就是说,传递给JIT编译器的编译实体是一个基本块,有时与单个指令一样短.这些跟踪将在运行时通过称为链接的技术拼接在一起,以便不会经常调用解释器和代码缓存查找.在某种程度上,加速的主要来源是消除重复的解释器解析频繁执行的代码路径上的开销.

也就是说,我们确实使用Froyo JIT实现了很多本地优化:

  • 寄存器分配(由于JIT为v7生成Thumb代码/ 16个寄存器,因此v5te目标有8个寄存器)
  • 调度(例如Dalvik寄存器的冗余ld/st消除,负载提升,存储下沉)
  • 冗余空检查消除(如果可以在基本块中找到这种冗余).
  • 循环形成和优化简单计数循环(即循环体中没有侧出口).对于这样的循环,基于扩展归纳变量的数组访问被优化,以便仅在循环序言中执行空值和范围检查.
  • 每个虚拟调用点的一个条目内联缓存,在运行时进行动态修补.
  • 窥视孔优化,例如mul/div的文字操作数的降低功率.

在Gingerbread中,我们为getter/setter添加了简单的内联.由于底层JIT前端仍然是基于简单的跟踪,如果被调用者在那里有分支,则不会内联.但是实现了内联缓存机制,以便可以毫无问题地内联虚拟getter/setter.

我们目前正致力于将编译范围扩展到简单的跟踪之外,以便编译器具有更大的代码分析和优化窗口.敬请关注.

  • 您已经注册专门回答这个问题?谢谢!太糟糕了,运营商推出姜饼的速度太慢了; 我认为至少在另一年里不能指望那些优化.这都是好东西,但由于我不是编译器编写者,我很难看到如何在实践中应用它.特别是: ... (11认同)
  • @Ben +1你能在这个时候回顾一下Ant所做的优化,考虑到这个问题仍然有意义.那将是真棒! (3认同)
  • (1)如果循环的上限取决于非最终变量(例如字段),或者我应该将上限存储在最终的局部变量中,是否也进行循环优化?(2)重复访问的所有字段的相同问题.(3)我应该尽可能地宣布我的方法`final`吗?或者这仍然算作虚拟呼叫站点?(4)一般情况下内联不是在JIT级别进行,但也许你碰巧知道编译器和/或dx工具是否这样做了? (2认同)
  • (1)只要上限/下限是循环不变量,声明一个局部变量并在循环外读取它是最干净的方法.(2)JIT尚未进行循环不变优化.因此,您再次想要在循环外部刻录一个局部变量来读取它.(3)是的请(4)我们希望保持开发人员调试代码的能力,因此dx不执行内联.但很快JIT将积极进行内联. (2认同)

Oct*_*ean 10

我确信我的答案不会回答你所有的问题,但我想如果它能回答一个问题,那将是一场胜利.

您似乎对该主题有深刻的了解并知道您想要什么,因此您可能希望执行以下操作.构建一个包含要调查的方面的示例应用程序.

拿你获得的APK并通过APK工具运行它.正如我们所知,反向设计您自己的代码以完成您想要的内容.

APK工具将提取和解码您的资源,并将.dex文件反向工程到.smali文件.您可能还想查找smali项目以获取有关如何读取.smali文件及其限制的更多信息.

我再次确信这不会回答你所有的问题,但这可能是一个好的开始.


Jes*_*eke 5

首先,让我先说一下我不是dalvik的专家,我的一些回答可能是错的.但是我已经在dalvik中挖掘了JIT代码,而且我对dalvik运行的字节码非常熟悉.

  1. 方法内联 - 据我所知,这种情况从未发生过.我几乎肯定它永远不会发生在字节码级别,我认为它目前不会发生在JIT级别 - 尽管它可能在将来发生.

  2. 公共子表达式消除 - 我相信这只能用于不使用任何非最终变量/字段的子表达式.如果即便如此,我也不会完全肯定.如果完成,我希望它可以在字节码级别完成,可能不是JIT级别.

  3. 检查数组查找的边界 - 没有线索

  4. 价值内联 - 据我所知,是的 - 它们将在所有这些场景中被内联.

  5. 分支预测 - 不确定

  6. 简单的算术 - 据我所知

另外,我想提一下另一种方法 - dx和dalvik都是开源的,所以你可以随心所欲地挖掘它们.虽然,它们显然不是小代码库,但是需要花费相当多的努力才能在这个级别上深入挖掘它们