加入收藏 | 设为首页 | 会员中心 | 我要投稿 西安站长网 (https://www.029zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 业界 > 正文

9102年了,还不知道Android为什么卡?

发布时间:2019-08-15 09:10:20 所属栏目:业界 来源:吃猫猫的鱼
导读:副标题#e# 导读 最近华为方舟编译器要开源了,笔者去看了下发布会PPT,发现作为一名Android开发者,PPT中所介绍的知识点我居然不能完全看懂?于是乎恶补了下PPT中的内容,整理成本文。 本文将用通俗的语言从底层介绍Android卡顿的历史原因和谷歌与之斗争的过

这个时候有个严重的问题,首先上图 (图片参考方舟编译器原理PPT):

9102年了,还不知道Android为什么卡?

在开发阶段Java源代码在开发阶段打包成.dex文件,C语言直接就是.so库,因为C语言本身就是编译语言。

在用户手机中,APK中的.dex文件(字节码)会被解释为.oat文件(机器码)运行在ART虚拟机中,.so库则为计算机可以直接运行的二进制代码(机器码),两份机器码要互相调用肯定是有开销的。

下面就来阐述下为什么两份机器码会不同。

这边需要深入理解字节码->机器码的编译过程,在图上虽然都被编译成了机器码,都能被硬件直接调用,但是两份机器码的性能,效率,实现方式相差甚多,这主要是由以下两个点造成的:

  • 编程语言不同导致编译出的字节码不同导致编译出的机器码不同。
  • 举个例子,针对同样是静态语言的C和Java,对int a + b 的运算
  • C语言可以直接加载内存,在寄存器中计算,这是由于C语言是静态语言,a和b是确定的int对象。

在Java中虽然定义对象我们也要明确的指出对象的类型,例如int a = 0,但是Java拥有动态性,Java拥有反射,代理,谁也不敢保证a在被调用时还是int类型,所以Java的编译需要考虑上下文关系,即具体情况具体编译。

所以连字节码已经不同了,编译出的机器码肯定不同。

运行环境不同导致编译出的机器码不同

图中明显看到由Java编译而来的机器码包裹在ART中,ART全称Android RunTime,即安卓运行环境,跟虚拟机差不多是一个意思。而C语言所在的运行环境不在ART中。

RunTime提供了基本的输入输出或是内存管理等支持,如果要在两个不同的RunTime中互相调用,则必然有额外开销。

举个例子,由于Java有GC(垃圾回收机制),在Java中的一个对象地址不是固定的,有可能被GC挪动了。即在ART环境中跑的机器码中的对象的地址不固定。可是C语言哪管那么多幺蛾子,C就直接问Java要一个对象的地址,但万一这个对象地址被挪动了,那就完蛋了。解决方案有两个:

把这个对象在C里再拷一份。很明显这造成了很大的开销。

告诉ART,我要用这个对象了,GC这个对象的地址你不能动!你先一边呆着去。这样相对而言开销倒是小了,但如果这个地址如果一直不能被回收的话,可能造成OOM。

(此处参考知乎@张铎在华为公布的方舟编译器到底对安卓软件生态会有多大影响?中的回答)

3. 字节码的编译模板——未针对具体APP进行优化

我们举个例子来理解编译模版,“Hello world”可以被翻译为“你好,世界”,同样也可以被翻译为“世界,你好”,这个差别就是编译模版不同导致的,

①. 统一的编译模版(vm模版)

(编辑:西安站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读