【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

Flash Player 和 Adobe AIR 垃圾收集内幕

  • 2011-11-17
  • 本文字数:3951 字

    阅读完需:约 13 分钟

目录

需求

预备知识

本文适用于中级和高级 ActionScript 开发人员。需要对面向对象的编程概念和 ActionScript 3 开发具有中等程度的理解。

用户水平

中级

需要的产品

所有应用程序都要管理内存。应用程序的内存管理包括用于确定何时分配内存,分配多少内存,何时将内容放入回收站,以及何时清空回收站的准则。MMgc 是 Flash Player 用于几乎所有内存分配工作的通用内存管理器。理解 MMgc 如何管理内存是优化您的代码和您应用程序的性能的一个重要部分。

垃圾收集器自动回收的内存被视为“受管理的内存”。垃圾收集器确定内存何时不再被应用程序使用并回收它。本文分析 Flash Player 11 和 AIR 3 中的内存分配、垃圾收集流程和新的 pauseForGCIfCollectionImminent()API。

内存分配

Flash Player 使用一个页面分配程序(GCheap)来从 OD 分配大块(几 MB)的内存。Gcheap 然后将大内存块分解为较小的 4K 页面,并根据需要将这些页面提供给垃圾收集(GC)内存管理器。

图 1. GCHeap 从 OS 分配内存,将它分解为 4K 的页面,并将这些页面提供给 GC。

GC 然后使用这些 4K 页面为系统中不大于 2K 的对象提供内存。

图 2. 4K 页面由 GC 分配给小于 2K 的对象

对于大于2K 的对象(位图、视频、文件等),GCHeap 向一个大型的内存分配程序提供一组连续的4K 内存块。

当一个大内存块中几乎所有4K 页面都分配了时,Flash Player 运行垃圾收集来回收未使用的内存,然后GCHeap 尝试从OS 分配更多内存。换句话说,垃圾收集仅由内存分配触发。这一事实很重要,在测试和分析期间一定要记住,因为它意味着空闲应用程序的内存使用从不会改变。

堆和堆栈

堆是分配给在运行时创建或初始化的任何对象的内存。堆上的对象会一直存在到它们被垃圾收集。

图3. 对象A 存在于堆上。它由堆栈上的局部变量o 引用。(图字:堆栈内存 堆内存)

堆栈是存储在编译时定义的所有变量的内存。堆栈内存以一种顺序方式使用和重用。推送操作将一些内容添加到堆栈顶部。弹出操作从堆栈顶部删除一些内容。访问堆栈中间的内容的唯一方式是删除它上方的所有内容。

局部方法变量、参数和关于在一个方法完成时返回到何处的信息,在方法运行时被推送到堆栈上。对堆栈的更改发生得非常快。对象的堆栈引用可能非常短暂。这些对象引用可能存在于堆栈上,但分配给这些对象的内存来自堆。

图4. 局部变量在定义时被推送到堆栈上。关于在一个方法完成时返回何处的信息也推送到堆栈上。

Flash 运行时垃圾收集实现

Flash Player 和 AIR 结合使用延迟的引用计数和保守的标记并清除(mark-and-sweep)方法。

延迟的引用计数

在延迟的引用计数中,堆和堆栈引用之间存在区别。因为堆栈变化很快,并可能包含非常短暂的引用,所以引用计数不会在堆栈引用上执行。而在堆上为引用维护引用计数。

图 5. 对象会跟踪它们拥有多少个引用。

堆上的每个对象会跟踪指向它的信息数量。每次您创建一个对象的引用,该对象的引用计数就会递增。当您删除一个引用时,该对象的引用计数会递减。如果对象的引用计数为0(没有任何信息指向它),它会被添加到零计数表(Zero Count Table,ZCT)中。当ZCT 填满后,就会扫描堆栈以查找任何从堆栈到ZCT 上的对象的引用。ZCT 上任何没有堆栈引用的对象都会被删除。

延迟引用计数的一个问题是循环引用。如果ObjectA 和ObjectB 彼此引用,而系统中没有其他对象指向它们,它们将从不会拥有一个零引用计数,因此从不满足使用引用计数进行垃圾收集的资格。这时可以使用“标记并清除”的垃圾收集方法。

图6. Object A 和Object B 彼此引用,但没有其他引用。

标记/ 清除

在Flash Player 或AIR 中运行的应用程序具有多个GCRoot。您可以将GCRoot 视为一个树的一部分,它将应用程序的对象当作树枝。舞台是一个GCRoot。加载程序是GCRoot。某些菜单是GCRoot。让在供应用程序使用的每个对象可从应用程序内的一个GCRoot 访问。GCRoot 从不会被垃圾收集。

应用程序中的每个对象有一个“标记位”。当垃圾收集的标记阶段开始时,所有这些标记位会被清除。MMgc 会跟踪应用程序中的所有GCRoot。垃圾收集器首先从这些根开始,跟踪每个对象并为它到达的每个对象设置标记位。任何不再能够从任何根到达的对象也不再能够从应用程序的任何地方到达——它的标记位不会在标记阶段设置。收集器完成对它找到的所有对象进行标记之后,就会开始清除阶段。任何没有设置标记位的对象都会被销毁,它的内存会被回收。

图7. 一个循环引用中的对象没有被标记。

图7 显示,每个可从Gcroot 到达的对象都设置了自己的标记位(蓝色)。一个循环引用中的两个对象(ObjectA 和ObjectB)不可从GCRoot 到达。它们的标记位将不会设置。因此,即使它们没有零引用计数,这两个对象也会被垃圾收集。

弱引用

Flash Player 也可以维持对某些类型的对象的“弱引用”。弱引用是一种对垃圾收集器的正常跟踪过程(跟随所有根来查找可到达的对象的过程)不可见的引用。

当您实例化一个新字典时,可以表明您希望它与字典的键建立较弱的关联。

复制代码
var d:Dictionary = new Dictionary( true );
d[ someObject ] = someValue;

您也可以在添加事件监听器时,将 addEventListener() 的函数 useWeakReference 参数设置为 true。

复制代码
obj.addEventListener( "type", handler, false, 0, true );

在这两种情况下,您都会要求Flash Player 在两个对象之间建立引用,但以一种较弱的方式保持该引用。具体来讲,这意味着这个具体的引用在标记期间不会被跟随。

图8. 若引用在标记期间不会被跟踪。

在这种情况下,到Object B 的唯一路径是弱的。在跟踪期间将不会经过它,因此Object B 不会被标记,并会被收集。但是,如果还有另一个到Object B 的强路径,Object B 将被标记并被持久化。

图9. 具有强引用的对象将在跟踪期间被找到并标记。

您应该始终清理未使用的引用,从字典删除未使用的项,以及使用removeEventListener()。但是,有时清理未使用的引用不切实际或无法做到。比如在您的类在您不知情的情况下实例化和销毁时——项渲染器就是通过这种方式使用的。在这些情况下,维持对象的若引用将允许Flash Player 最终删除它们并回收内存。

保守收集

MMgc 被视为一种保守的标记 / 清除收集器。MMgc 无法确定内存中的某些值是对象指针(内存地址)还是数字值。为了避免意外地收集值可能指向的对象,MMgc 假设每个值都可以是一个指针。因此,一些没有实际被指向的对象将从不被收集,将被视为一种内存泄漏。尽管您希望最小化内存泄漏以优化性能,但由保守的 GC 所导致的偶然泄漏可能是随机的,不会随时间增长,并且对应用程序性能的影响比开发人员导致的泄漏小得多。

增量收集

不幸的是,垃圾收集可导致Flash Player 在收集过程完成时定期暂停。这种暂停与应用程序当前运行的内存量成正比。它可能比希望的时间更长,在一些程序中可以察觉到。

标记阶段是垃圾收集过程中最消耗时间的部分。由于此事实,标记过程使用一个动作队列和一个3 色算法增量化了。该队列在标记增量之间维护标记状态。

表1. 3 色算法

clip_image013[4]

黑色对象已标记,不再位于队列中。

clip_image015

灰色对象位于队列中,还未被标记。

clip_image017

白色对象既未标记也不在队列中。

在标记阶段的开始,所以GCRoot 被推送到队列中并变为灰色。

图10. GCRoot 在推送到工作队列中时变成灰色。

随着标记过程的继续,标记的对象变为灰色,并从工作队列删除。

图11. 标记的对象是黑色的,不再在工作队列中。

此过程会正常继续进行,直到将一个新对象(白色)添加到一个黑色对象上。当发生此情况时,白色对象从不会设置它的标记位,因为它们的GCRoot 已标记。不设置它们的标记位,它们将在清除阶段被垃圾收集。

图12. 新对象被添加到以前标记的对象上。

要预防此问题,可以在MMgc 中使用一个白色边界来强制将任何添加到黑色对象上的白色对象立即添加到工作队列中。

图13. 添加到以前标记的对象中的新对象被立即添加到工作队列中。

通过使用工作队列和3 色算法,可开始和停止标记阶段来帮助避免长时间、意外的垃圾收集暂停。

迫近度

标记阶段可能是垃圾收集中最耗时的部分,但实际上清空回收站(重新分配空闲内存)也比较耗时。重新分配还可能导致应用程序暂停。垃圾收集器离标记阶段的完成和清除(重新分配)阶段的开始的时间称为“迫近度(imminence)”

图14. 迫近度(图字:标记 暂停、迫近度增长)

public static function pauseForGCIfCollectionImminent(imminence:Number = 0.75):void 是 Flash Player 11 和 AIR 3 中的一个新方法,允许您通知垃圾收集器这是完成标记和执行收集的好时机( ActionScript 参考文档中的 API 项)。计划在用户不会注意到时发生可能的暂停,这会带来更好的用户体验。例如,一个游戏可能在游戏中一个级别完成时调用此函数,进而减少在玩游戏期间发生暂停的机会。

您传递给此方法的迫近度值用于与垃圾收集器处于标记阶段中的位置进行比较。如果您传递给它的值比垃圾收集器的迫近度值小,标记和清除将同步完成并导致应用程序暂停。垃圾收集器必须处于该过程的 25% 以上,才能响应这个暂停以进行收集的请求。传递一个较小的值(但大于 0.25)很可能会强制执行收集,导致应用程序暂停。传递一个较大的值将告诉垃圾收集器只有在即将暂停时完成收集。

延伸阅读

理解内存管理和垃圾收集在Flash Player 和AIR 中的工作原理,将有助于您优化您的代码并开发更高性能的应用程序。请查阅Michael Labriola 介绍垃圾收集的演示 Talking Trash 。阅读 Christian Cantrell 的 Providing Hints to the Garbage Collector in AIR 3 。您也可以阅读详细的 MMgc 讨论,其中包含对底层 C++ 代码的描述。

查看原文: Garbage collection internals for Flash Player and Adobe AIR

2011-11-17 20:491878

评论

发布
暂无评论
发现更多内容

web前端培训Vue3 TypeScript 如何实现useRequest

@零度

Vue 前端开发

CopyOnWriteArrayList 源码分析-其它方法

zarmnosaj

5月月更

【linux运维】linux运维会被淘汰吗?会消失在云计算中吗?

行云管家

云计算 IT运维 云运维

智能手表的机遇与挑战

Geek_99967b

物联网

如何在 JavaScript 中让代码更加精简

devpoint

ES6 6月月更

小程序转App仅需7步

Speedoooo

ide APP开发 小程序转app 前端IDE

中小互联网公司研发效能团队规模、职能划分和优劣势分析

laofo

DevOps cicd 研发效能 持续交付 互联网公司

服务端技术进阶(三)从架构到监控报警,支付系统设计如何步步为营

No Silver Bullet

架构 支付系统 架构设计 5月月更 监控报警

纪念左晖:敢为天下先(修订版)

IT民工大叔

产业互联网 数字化转型 企业家精神 左晖

小程序生态构建能力,离不开UI定制自由

Speedoooo

ide 小程序ide

IOC思想开窍之路

留乘船

Java spring ioc

性能优化手记上篇之【原则】&【方法】

鲸品堂

SREWorks持续交付云原生化: 镜像构建

阿里云大数据AI技术

大数据 运维 云原生

大数据培训实时数仓实践以及架构的演进

@零度

数仓 大数据开发

探密"一学就会,一用就废"的OKR

Bruce Talk

OKR 敏捷 Agile

如视技术副总裁杨永林:当传统产业遇到“数字空间”

阿里云弹性计算

视觉计算 数字空间 VR看房

CC2530 ADC配置步骤

DS小龙哥

5月月更

拯救工程师,远程开发C++的四大秘笈|视频教程

OneFlow

c++ 教程分享

架构的尽头是架构师

IT民工大叔

架构师

虚拟机是什么?跟堡垒机有哪些区别?

行云管家

虚拟机 堡垒机

eBPF 简介

申屠鹏会

ebpf

SAP UI5 框架的 manifest.json

Jerry Wang

前端开发 SAP Fiori SAP UI5 5月月更

高校学生请注意:想成为技术大牛,参加这个计划就够了!

科技热闻

校企融合,打造金融科技应用人才高地

非凸科技

校企合作 非凸

浅析数字化转型与产业互联网

IT民工大叔

产业互联网 数字化转型

3000帧动画图解MySQL为什么需要binlog、redo log和undo log

CoderW

后端 面试题 Binlog Redo Log MySQL 数据库

王者荣耀商城异地多活架构设计

小虾米

架构师实战营

没有JDK和Maven,用Docker也能构建Maven工程

程序员欣宸

Java Docker maven 5月月更

企业电子文档管理需要注意的点及解决措施

小炮

文档管理

“技术商人”溯源考

IT民工大叔

华为 工程师 任正非讲话 商业意识 复合型人才

java培训SpringBoot 中的各种参数校验

@零度

JAVA开发 springboot

Flash Player和Adobe AIR垃圾收集内幕_DevOps & 平台工程_Michelle Yaiser_InfoQ精选文章