掌桥专利:专业的专利平台
掌桥专利
首页

表示用于无暂停垃圾收集的激活帧的方法和装置

文献发布时间:2023-06-19 09:30:39


表示用于无暂停垃圾收集的激活帧的方法和装置

背景技术

本申请总体上涉及计算机存储器管理领域,具体地涉及用于高性能、时间关键的应用程序的垃圾收集过程。

背景技术

对于计算机,垃圾收集是指识别主存储器存储的未使用区的过程。根据面向对象的计算语言,执行程序的计算机为每个对象分配存储器。存储器被分配给块—大小根据应用要求而设定—组成的堆,从堆释放。最后,当对象不再被程序引用时,通过垃圾收集过程收回为创建的对象分配的存储器。垃圾收集过程从存储器中清除对象,曾经分配的存储器从而再次可用。更具体地,垃圾收集过程可以涉及通过标记正在使用的对象来自动确定哪些存储器块可以被释放并且收回未标记的对象的存储器。这样的垃圾收集过程通常被称为标记-清除(mark-and-sweep),因为存储器的有用部分在标记阶段期间被标记为活动的,并且所有未标记的对象随后在清除阶段中从所分配的存储器移除。尽管垃圾收集的过程释放了存储器,但是,在垃圾收集过程的不可预测的处理器时间消耗影响应用程序运行的应用程序中,可能会出现问题。

发明内容

本发明提供了如权利要求1所述的方法,以及相应的系统和计算机程序。

附图说明

参考以下附图和描述将更好地理解贯穿本文档描述的实例。附图中的部件不一定是按比例绘制的。此外,在附图中,贯穿不同的视图,相同附图标记指代对应的部分。

图1示出了示例多任务计算机系统;

图2示出了程序堆栈以及存储在程序堆栈上的典型激活帧的框图;

图3示出了根据一个或多个示例的用于无暂停垃圾收集的无暂停激活帧;

图4示出了用于执行线程堆栈的后台扫描以进行无暂停垃圾收集的示例方法的流程图;

图5示出了用于协调应用程序线程和垃圾收集线程对线程堆栈的扫描的示例方法的流程图;

图6示出了用于在从先锋方法(vanguard method)返回时扫描调用者的激活帧并标识新的先锋方法的示例方法的流程图;和

图7示出了针对由进程线程(process thread)进行的垃圾收集而执行的程序堆栈扫描的示例场景的可视表示。

具体实施方式

在此参考相关附图描述本发明的不同实施例。在不脱离本发明的范围的情况下,可以设计本发明的替代实施例。在以下描述和附图中的元件之间阐述了各种连接和位置关系(例如,上方、下方、相邻等)。除非另有说明,这些连接和/或位置关系可以是直接的或间接的,并且本发明在这方面并示意图进行限制。因而,实体的耦合可以指直接或间接耦合,并且实体之间的位置关系可以是直接或间接位置关系。此外,本文所述的各种任务和工艺步骤可并入到具有本文未详细描述的附加步骤或功能的更全面的程序或工艺中。

以下定义和缩写用于解释权利要求书和说明书。如在此使用的,术语“包括”、“包含”、“具有”、“含有”或“含”或其任何其他变体旨在覆盖非排他性的包括。例如,包含一系列元素的组合物、混合物、工艺、方法、制品或设备不一定仅限于那些元素,而是可包括未明确列出的或此类组合物、混合物、工艺、方法、制品或设备固有的其他元素。

此外,术语“示例性”在此用于指“用作实例、实例或说明。”本文中描述为“示例性”的任何实施例或设计不一定被解释为比其他实施例或设计优选或有利。术语“至少一个”和“一个或多个”可以被理解为包括大于或等于一的任何整数,即.一个、两个、三个、四个等。术语“多个”可以理解为包括大于或等于2的任何整数,即.两个、三个、四个、五个等。术语“连接”可包括间接“连接”和直接“连接”两者。”

术语“约”、“基本上”、“大约”及其变体旨在包括与基于在提交本申请时可用的设备的具体量的测量相关联的误差程度。例如,“约”可以包括给定值的±8%或5%、或2%的范围。

为了简洁起见,与制作和使用本发明的多个方面相关的常规技术可以或可以不在此详细描述。具体地,用于实现本文描述的不同技术特征的计算系统和特定计算机程序的不同方面是公知的。因而,为了简洁起见,许多常规实现细节在此仅简要地提及,或者完全省略,而不提供公知的系统和/或过程细节。

参见图1,示出了典型的多任务计算机系统100,其具有CPU 102、用户接口106和存储器108,存储器108包括用于存储的随机存取存储器(RAM)和非易失性存储器。存储器108存储受管理的运行时环境110和一个或多个进程112,每个进程可以包括一个或多个线程。系统中的每个活动进程被分配计算机的存储器的一部分,包括用于存储由进程执行的应用级代码112的空间、用于动态存储器分配的堆(heap)116,用于表示正在执行所述进程的每个线程的状态的空间,以及用于存储每个线程的程序堆栈114的空间。受管理的运行时环境110还包括调度管理程序148,调度管理程序148负责决定要将CPU时间专用于正在执行的多个任务中的哪一个。通常,调度管理程序148必须在运行应用进程线程与运行垃圾收集线程之间权衡。进一步,在管理的运行时环境110内,多个独立开发的应用可以同时运行。

每一线程的程序堆栈114可以不在存储器108的连续页中,且如果不是连续的,那么使用已知技术将堆栈存储的页或可能更大的连续组块(chunks)链接在一起。应当注意,在进程112内,存在多个线程,并且每个线程具有其自己的程序堆栈114。

CPU 102包括用于向指令解码器和执行逻辑122提供指令的指令高速缓存120。CPU102还包括用于在高速的高速缓存存储器中存储程序堆栈114的一部分的堆栈高速缓存124,以及用于存储数据值、对象引用128等的寄存器组126。包括堆栈高速缓存124中的该部分的程序堆栈114用于临时存储不同数据结构和参数,包括每次方法或其他过程被调用时推送在程序堆栈114上的激活帧130(或记录)。

在某些垃圾收集阶段的开始,垃圾收集器扫描指针的根集合132。应当注意,尽管图1将根集合132描绘为单个块,但是根集合132包括机器寄存器和某些全局存储器位置,并且根集合可以作为负责根集合的扫描的计算机可执行指令的一部分被编码在垃圾收集器中。根集合表示有限数量的机器寄存器和存储器位置,它们的累积提供对当前由进程112使用的所有对象的间接访问。在无暂停垃圾收集系统中,根集合132中的变量的数量非常小,通常少于100。根集合不包括各个线程堆栈的内容或所有线程描述的内容。相反,根集合通常包括对数据结构的引用,该数据结构跟踪所有线程描述。每一线程描述又保持跟踪相关联的线程堆栈。

应当理解,图1仅描绘了CPU 102和存储在存储器中的项目的简化表示。而且,应当理解,多个过程可在计算机系统中同时执行,每个过程具有其自己的地址空间,该地址空间包括如图1的存储器108中所示的相同类型的项目。

术语“对象”(object)在此被定义为是指由程序或过程创建的任何数据结构。术语“引用”(reference)和“对象引用”可互换使用以描述包括指向对象的指针的数据结构。虽然术语“指针”或“对象指针”有时与“引用”和“对象引用”可互换地使用,但是对象引用可以包括除了指针之外的信息。对象引用可以是直接或间接的。直接对象引用直接指向对象头部,而间接对象引用指向对象句柄。如在此使用的,术语“对象引用”是指两种类型。

当与堆116相关联的进程112需要用于存储阵列或其他程序“对象”的空间时,存储器分配器例程140被调用(called/invoked)。存储器分配器140通过将堆116中未使用的存储器的块分配给进程112来响应。对存储器的额外请求导致额外存储器块的分配。如果进程112继续请求更多存储器,则堆116中的所有空间将最终被使用并且进程112可能由于缺乏存储器而失败。因此,必须通过程序的显式行动或一些其他机制来补充空间。

通常,进程112“放弃”(abandon)分配给它的对象的许多存储空间。通常,进程112将对程序对象的引用存储在所分配的存储器块中,并且在进程完成对某些对象的处理之后,覆写(overwrite)对某些对象的所有引用,因为进程将永远不需要再次访问那些对象。不存在对其的引用(有时被称为指针)的对象通常被称为“不可访问的对象”或“垃圾”,并且对象占用的存储器空间对曾经使用过它的进程112“不可访问”。

通过恢复堆116中不再被进程112使用的存储器空间的块来解决该技术问题。垃圾收集是用于指恢复堆116中未使用的存储器的自动方法的术语。垃圾收集器142用于恢复堆116中的存储器的未使用或废弃部分,使得使用该堆的进程112将不会耗尽存储器。编程语言的管理的运行时环境包括垃圾收集器142。垃圾收集器142在预定事件发生时收集并恢复未使用的存储器,所述预定事件诸如预定时间段的期满或一定量的可用堆的使用。

垃圾收集器142可以使用任何不同的垃圾收集方法,诸如停止并复制(stop-and-copy)垃圾收集技术。在该方案中,堆116被划分成两半,也称为半空间,并且程序一次仅使用一个半空间。停止并复制垃圾收集器回收未使用的存储器并且通过将旧的半空间(通常被标识为from-space)中的所有“可访问的对象”复制到另一半空间(通常被称为to-space)中的存储器的连续块来压缩由进程112使用的程序可访问的存储器,以及改变对可访问对象的所有引用以便指向这些对象的新副本。可访问的对象是由任务的“根”或“根集”直接或间接引用的任何对象(即,存储器块)。通常,关于垃圾收集的进程112的根集合132是存储在已知位置(诸如某些机器寄存器126和某些全局变量)中的对象引用的集合,其指向由进程112使用的对象。这些对象中的许多对象进而将包含对进程112所使用的其他对象的引用。从根集合发出的对象引用的链或有向图间接地指向堆116中的所有可访问的对象。

通过将所有可访问的对象复制到堆116中的新连续存储器块,然后使用对象的新副本代替旧副本,停止并复制垃圾收集器142消除了堆116中的所有未使用的存储器块。它还“压缩”由任务使用的存储器存储,使得在可访问的对象之间不存在“空隙”。压缩是期望的属性,因为它将可用于分配给任务的所有存储器放在连续块中,这消除了跟踪未分配存储器的许多小块的需要。压缩还改进虚拟存储器性能。

应注意,尽管本文描述了停止并复制垃圾收集,但即使垃圾收集器142使用任何其他技术,诸如增量式垃圾收集或必须扫描每个线程堆栈的内容以便识别使用中对象的任何垃圾收集系统,本文描述的技术方案也是适用的,并且适用于需要快速且高效地定位从线程激活记录内做出的对象引用的任何跟踪垃圾收集系统。应当注意,停止并复制垃圾收集不适合于无暂停垃圾收集,因为该技术引入非常长的暂停(范围从几百毫秒到几十秒),应用程序在复制期间被停止。增量式标记-清除和增量式复制技术更适合于无暂停垃圾收集。

图1中还示出了被设置为执行JAVA

时间关键的JAVA软件已经成功地部署在一系列领域中,包括对制造自动化、电力管理、自动车辆、电信基础设施和武器系统的控制。这些成功部署的应用证明,Java的高级益处可以被时间关键的开发者利用并得到重视,尽管以Java实现的实时应用比以C实现的相同应用需要更多的CPU和存储器资源。Java最适合用于没有部署在高(消费电子产品)卷中的大型且复杂的时间关键的应用。利用这些应用,与软件的开发和维护相关联的成本和风险通常远大于在其上部署软件的计算硬件的总成本。这些是使Java开发者在新功能的实现期间的生产率常常是基于C或C++的传统方法的两倍,而在重用、维护和重新利用现有功能方面的生产率通常是其十倍以上。

采用时间要求严格的Java技术的两个技术障碍是:(1)由于应用程序线程112和垃圾收集142活动之间的细粒度协调的开销,时间要求严格的Java虚拟机比传统的Java虚拟机运行慢得多,以及(2)即使在响应速度最快的实时Java虚拟机上,传统Java线程112的响应延迟也大约为200μs。这大致比用C编写的类似线程的典型响应延迟慢20倍。本文描述的技术方案解决了这样的技术难题,实现了与传统Java相当的吞吐量和与C编写的应用程序相当的响应延迟。因此,本文描述的技术方案通过促进对高性能,时间紧迫的Java程序的无暂停垃圾收集,解决了植根于Java程序性能计算技术的技术难题,并改善了Java程序的执行。应当注意,尽管本文描述的示例使用Java程序,但是本文描述的技术解决方案适用于使用任何其他计算机编程语言或其组合编写的计算机程序,特别是如果所述语言使用垃圾收集来进行存储器管理。

本文描述的无暂停垃圾收集系统的总垃圾收集工作被分成工作的小增量,其与由进程112执行的应用程序代码的执行交错。为了确保可靠的操作,垃圾收集和应用努力的每个增量做出可测量的向前进展,如图5所示。进一步,因为Java对象在应用程序和垃圾收集线程之间共享,所以无暂停垃圾收集使用协议来确保数据一致性。每当垃圾收集器142重定位对象以便对存储器进行碎片整理时,进程112立即立即知道对象在存储器108中的新位置。同样,每当应用程序线程(即,进程112)覆写现有对象的指针字段或覆写在当前执行的方法中包含的激活帧内的指针时,垃圾收集器142立即识别出对象连通性图中的这种变化,因为这可能改变垃圾收集器142对“垃圾”—即不再由进程112使用的存储器—的感知。

Java应用开发者使用特殊语法来标记在线程之间共享的对象。这允许编译器优化对非共享对象的访问。可以将非共享对象的内容高速缓存在机器寄存器126中,并且对非共享对象的访问不需要存储器屏障来强制高速缓存一致性。Java编译器为仅处理私有(非共享)对象的线程生成非常有效的代码。没有这样的语法区分垃圾收集器142将要看到的对象。发出确保一致性的代码是编译器的责任和机会。

图2是程序堆栈以及存储在程序堆栈上的典型激活帧的框图。程序堆栈114存储两种方法激活帧(也称为栈帧/激活记录)。中间计算评估数据存储在激活帧内。每当调用新方法或过程时,都会将新的栈帧或激活帧130被推送到栈114上。

如图2所示,示例激活帧130包括返回地址编程计数器值以及其他元素。激活帧130还包括先前帧栈指针值(即,指向先前栈帧的开始,如果有的话)。激活帧130还包括与被调用过程或方法相关联的操作数参数160、162。激活帧130还包括与被调用过程或方法相关联的局部变量164、166。

此外,多个寄存器用于管理程序堆栈114的使用。例如,寄存器用于存储指向堆栈114的底部(base)的基础帧指针170,指向堆栈顶部(即,堆栈的未使用部分的开始)的堆栈顶部指针172,以及指向当前激活帧130的结尾的当前帧指针174。

在一个或多个实例中,受管理的运行时环境110包含用在相关联的线程堆栈114中存储被进程112调用的每个方法的激活帧130的指令。重申,使用常规术语,每当方法被调用或过程被调用时,激活帧130被推送到程序堆栈114上。每当过程退出时,数据处理器将其程序计数器设置为当前激活帧130中的返回地址PC,从程序堆栈114弹出当前激活帧130,并且先前激活帧变为新的当前帧174。

取决于被调用的方法,激活帧130中的参数160、162和局部变量164、166中的一个或多个可以是对象引用。通常,对于每种定义的方法,在激活帧130中都有固定数目的参数和固定数目的局部变量,并且对于激活帧130中的每个参数和变量,都有固定的预定义数据类型。典型的数据类型包括长整数、短整数(16位带符号整数)、单精度浮点、双精度浮点、字节、字符和对象引用(有时称为对象句柄)。

在无暂停激活帧中,在距每个方法的激活帧的顶部地址的固定偏移处保留的预定空间,以保持在进程112和执行垃圾收集器142的线程之间共享的局部指针值。在方法执行的大部分时间期间,指针变量被保持在机器寄存器中。在抢先于正在运行的线程之前,将所有活动指针变量保存在PointerVariablePreemptionSaveArea(指针变量抢占保存区)230中。在抢先之后,通过从PointerVariablePreemptionSaveArea读取保存的值来恢复指针寄存器的内容。存储和获取这些指针值几乎是空闲的(free免费的),因为这些指令替换应用程序二进制接口(ABI)的现有指令以保存和恢复围绕每个函数调用的非易失性寄存器。安排了抢占安全点,使得可以在不需要协调开销的情况下一次执行数百个指令(通常表示大约1μs的实时时间)。PointerVariablePreemptionSaveArea的维护即使不是免费的也是相当低成本的,因为维护它所执行的操作与已经执行的操作相当,实施本文描述的技术方案不会增加进一步的实质性计算成本。

大多数指针参数在机器寄存器中传递,并且大多数局部指针变量同样保持在机器寄存器中。在存储器中传递指针参数的情况下,编译器生成代码,以便在该方法对抢占请求让步之前,将指针参数的值复制到PointerVariablePreemptionSaveArea的槽中。如果必须在存储器中表示指针局部变量,则始终从PointerVariablePreemptionSaveArea内取得由编译器保留的用于表示局部变量的槽。

图3描绘了根据一个或多个示例的用于无暂停垃圾收集的无暂停激活帧。描绘了用于执行Java方法的无暂停激活帧200。然而,应当注意,无暂停激活帧200可以应用于任何其他的使用垃圾收集的计算机编程语言。除了参考图2所描述的典型元素,无暂停激活帧200包括对下一方法的对象引用210,该下一方法是由与当前无暂停激活帧200相关联的当前方法调用的。进一步,在一或多个实例中,无暂停激活帧200包括真返回地址字段(TrueLRSave)220,其表示调用与当前激活帧200相关联的方法的上下文。更进一步,在一个或多个示例中,当前无暂停激活帧200包括对指针变量抢占保存区(preemption savearea)230的引用。如果相关联的方法不具有抢占点,则可以不将真返回地址220和对抢占保存区230的引用存储在当前无暂停激活帧200中。

指针变量抢占保存区230是存储器位置的集合,其中存储了来自与当前无暂停激活帧200相关联的第一方法的所有活动指针。在一个或多个示例中,抢占保存区230包括用于存储活动指针的专用位置。第一方法中的一个或多个活动指针可以在代码生成时由编译器(未示出)确定。

图3还描绘了程序堆栈114中的第二无暂停激活帧205。第二无暂停激活帧205与调用与当前无暂停激活帧200相关联的方法(第一方法)的调用者(第二)方法相关联。第二无暂停激活帧205还包括字段210、220和230。

当第二方法准备调用第一方法时,第二方法用对提供与将要被调用的第一方法相关联的符号信息的MethodImplementation(方法实现)对象的应用,来重写其激活帧205的InvokedMethodImplementation(被调用方法实现)字段210。该符号信息被用来提供嵌入到每个抛出的异常中的堆栈跟踪信息、支持某些安全管理功能(其仅在调用链验证请求有风险操作的代码可被信任时,才允许有风险操作被执行)、以及促进符号调试。在无暂停垃圾收集环境中,MethodImplementation对象210还描述在每个抢占点处的PointerVariablePreemptionSaveArea220的状态。典型的方法前言程序(prologues)和结尾程序(epilogues)不访问激活帧的TrueLRSave或PointerVariablePreemptionSaveArea字段220和230。

代码生成器或编译器(未示出)假设每个方法调用可以导致被垃圾收集器142的抢占。因此,每个调用都被视为抢占点并且伴随有表1中的逻辑所描述的动作。

表1

假设每个指针变量都保持在易失性寄存器126中,这种保存和恢复活动指针的工作基本上是与现有ABIs中由其他编程语言(诸如由用于所有调用者保存的(易失性)寄存器126的C代码)执行的工作相同。

由于该方法调用协议的约定,通常不分配非易失性(被调用者(callee)保存的)寄存器126来表示指针变量。这是因为,这些代码生成约定使得每个指针变量在每次方法调用中都被视为无效。对于不使用本文描述的无暂停激活帧的语言,在从方法调用返回时恢复到特定指针变量的值与调用之前保存的值完全相同。然而,对于无暂停激活帧装置而言,被恢复至指针变量的值可能与保存到指针变量抢占保存区中的值不同。在垃圾收集器142重定位所引用的对象以便减少存储器碎片化的情况下,恢复的值可能与最初保存到抢占保存区230中的值不同。更进一步,被认为是活的指针变量的集合和抢占保存区内专用于保存每个活动指针变量的槽,可能因函数内的每个抢占点而不同。

如果第一方法需要比其对其他方法的调用所表示的更多的抢占点,则代码生成器将显式抢占检查插入到该方法的主体中。表2中示出用于实现显式抢占检查的代码。如果垃圾收集器142在该线程被抢占的同时开始扫描该线程的堆栈,则在允许该线程恢复执行438之前,垃圾收集器142针对被抢占方法434扫描指针变量抢占保存区230。被抢占的方法被称为先锋方法(vanguard method)。先锋方法的和从先锋方法直接或间接调用的任何方法的无暂停激活帧,不需要被扫描。当控制从先锋方法返回时,应用程序线程在执行实现先锋方法的调用者的任何代码之前自动地扫描封闭激活帧的指针变量抢占保存区,然后,先锋方法的调用者变成新识别的先锋方法。

表2

延迟上下文切换直到进程112的当前线程到达其下一个显式抢占点,会增加了响应延迟,但是使得能够增加在抢占点之间执行的代码的效率。当垃圾收集器142空闲时—通常超过应用程序的运行时间的90%,维持无暂停激活帧200对进程112的运行线程施加非常小的执行开销。在运行时间期间维持无暂停激活帧200通过促进递增地扫描每个线程的程序堆栈114而改善了进程112的响应延迟。

在不失一般性的前体下,假定每个应用程序线程与专用于扫描应用程序线程的堆栈的单个垃圾收集线程配对。配对的线程共享对单个硬件线程核的访问,使得在任何特定时间两个线程中的仅一个线程被允许执行。两个线程之间的上下文切换仅在指定的抢占安全执行点处发生,如由用于应用程序线程的编译器和由用于垃圾收集线程的管理的运行时间环境的开发者预先确定的那样。确保垃圾收集器142和进程112的应用程序线程不同时扫描同一堆栈,从而消除了对为防止对同一激活帧的共享槽(slots)的冲突访问的锁定协议的需要。应用程序线程和垃圾收集线程之间的替代的多对多映射,可以利用线程同步锁或利用智能集成线程调度器来实现,智能集成线程调度器仔细地避免调度应用程序线程在相关联的垃圾收集线程正在运行的同时运行。

图4描绘了用于执行线程堆栈的无暂停扫描作为垃圾收集活动的示例方法的流程图,该垃圾收集活动在时间关键的应用程序工作负荷的后台同时运行。该方法的多个实例可以同时运行,进程112中的每个活动线程一个实例。该方法包括垃圾收集器142线程与作为进程112的一部分执行的相关联的应用程序线程协同工作。垃圾收集器142线程扫描在系统100中执行的一个进程线程的堆栈114,垃圾收集器142已用信号通知扫描意图。通常,垃圾收集器142从每个堆栈的底部(较高存储器地址)开始扫描线程堆栈114,并朝其顶部进行扫描。线程堆栈114是作为后台活动被扫描的。

垃圾收集器142确定是时候扫描线程堆栈,因为先前阶段的垃圾收集的已经完成,或者由于内存分配池的大小已经缩小到特定阈值以下,或者因为已经达到了先前安排的开始某个垃圾收集阶段的时间,或由于任何其他预定条件。对于堆栈需要扫描的线程中的每一者,垃圾收集器142执行图4中所描述的方法。假定每一线程堆栈上的最底部激活帧与一个简单引导方法相关联,后者不具有显式抢占点且不维持除了其激活帧的InvokedMethodImplementation字段的值之外的指针。

在垃圾收集器选择进程线程以使其堆栈被扫描的时刻,垃圾收集器确保应用程序线程处于抢占状态。在该线程最近被抢先时运行的进程线程方法被标识为先锋方法。当为待扫描的对应程序堆栈114选择了进程线程时,在432,垃圾收集器142设置相关联的线程描述符的scan_base(扫描_底部)字段和scan_top(扫描_顶部)字段以标识需要扫描的无暂停激活帧的范围432;在434,它扫描先锋方法的指针变量抢占保存区230,在436,它通过用特殊跳转函数的地址覆写先锋方法的返回地址来通知进程112的进程线程帮助扫描其自己的栈帧。在这个设置工作430结束时,如果必要的话,垃圾收集器142进行让步以允许应用程序线程继续执行。执行这个设置工作430所需的时间非常小,通常小于1秒。由此,垃圾收集器142对应用程序线程的及时执行的干扰被表征为无暂停。

图5描绘了用于调度应用处理活动与后台垃圾收集活动之间的交替努力增量的示例方法的流程图。在进程112的执行期间,垃圾收集在大部分时间是空闲的。作为受管理的运行时环境110的一部分的线程管理程序148,负责调度将由垃圾收集器142和进程线程执行的工作的增量。如果垃圾收集是空闲的(460)或者如果应用程序线程比垃圾收集器更迫切地需要运行(462),则CPU时间的增量专用于进程线程的执行(464)。如果垃圾收集器的需求比进程线程更紧急(462),则CPU时间的增量专用于垃圾收集活动(468)。在极少数情况下,非常高优先级的进程112线程正在等待对堆的补充,以便可以分配新对象,垃圾回收活动会继承正在等待的进程线程的高调度优先级。最常见的场景是垃圾收集在低优先级运行,并通过在高优先级、时间关键的进程线程等待新工作的时间期间主动执行垃圾收集,来避免存储器内存不足的状况。进程线程和垃圾收集线程频繁地对抢占请求让步(466,470),使得新近准备好运行的任何高优先级任务都可以快速地获得对CPU 102的访问,以便及时地完成其工作。

在资源准许时,后台垃圾收集线程继续以后台活动的方式扫描线程堆栈,从而允许较高优先级进程112线程在前台中运行。在线程具有需要被扫描的无暂停激活帧(如由scan_top的值大于scan_base(440)所指示的)时的迭代的循环中,垃圾收集线程扫描属于在scan_base指针正下方找到的无暂停激活帧的PointerVariablePreemptionSaveArea字段的内容(452)。在扫描该激活帧之后,垃圾收集器调整scan_base变量的值以反映仍然需要被扫描的无暂停激活帧的新范围(454)。如果在扫描一个激活帧之后,该线程上不再有激活帧要被扫描(455),垃圾收集器将为该线程的当前先锋方法的调用者覆写LRSave字段,使得当先锋方法返回时,控制将返回到先锋方法的原始调用者而不是跳转子例程(456)。垃圾收集器142频繁地对抢占请求让步,使得准备好运行的较高优先级进程线程可以快速地获得对CPU 102的访问,以便及时地完成工作(458)。

当控制从先锋方法返回时,提供特殊处理。控制不是直接返回到最初调用先锋方法的方法,而是返回到一个特殊跳转子例程,其由图6所示的流程图表示。跳转子例程检查调用者的激活帧是否已经被后台垃圾收集线程扫描480。如果调用者的帧尚未被扫描,则跳转子例程扫描激活帧482并且调整线程描述符的scan_top变量的值以将新扫描的激活帧标识为属于新选择的先锋方法。

在跳转子例程扫描新选择的先锋方法的激活帧的情况下,跳转子例程进一步检查新选择的先锋方法的调用者的激活帧是否也需要被扫描486。如果是,则跳转子例程通过重写调用者的无暂停激活帧的LRSave和TrueLRSave字段488,来安排在控制从新选择的先锋方法返回时扫描该激活帧。

跳转子例程执行的最终动作,是通过分支到新近当前激活帧的TrueLRSave字段中保持的地址来将控制返回到先前运行的方法的调用者。

在开始程序堆栈114扫描后被进程线程调用的方法的激活帧不被扫描。图7提供针对由进程线程为垃圾收集而执行的程序堆栈扫描的示例情形的视觉表示。程序堆栈114包括已经被垃圾收集器142扫描的无暂停激活帧510。无暂停激活帧510与已调用其他方法并且等待所调用的方法从其执行返回的方法相关联。被调用的其他方法包括与无暂停激活帧200相关联的先锋方法,该先锋方法由与调用者的无暂停激活帧205相关联的调用者方法来调用。进一步,程序堆栈114包括对应于被先锋方法调用且在先锋方法之后被调用的方法的无暂停激活帧530。通过在程序堆栈114上推送对应的无暂停激活帧的顺序来表示方法被调用的顺序。

在450,并行地,垃圾收集器142从其用信号通知了扫描意图的进程线程扫描一个或多个方法的无暂停激活帧510。例如,将扫描作为后台活动与进程线程的执行同时执行。

因而,垃圾收集器142使用进程线程来执行增量堆栈扫描,其中进程线程垃圾收集器142扫描堆栈114中的其他无暂停激活帧基本上同时地扫描一个或多个无暂停激活帧。如本文所述,堆栈114包括多个无暂停激活帧,每个帧对应于来自正由计算机系统100执行的计算机程序的一个相应的方法调用。换言之,进程112中的每一方法调用,都在正在执行进程112的线程的编程堆栈114中创建一个对应的无暂停激活帧200。在一个或多个示例中,每个进程线程具有其自己的编程堆栈114。如果方法(例如方法-3(图7))调用另一方法(例如方法-4(图5)),则方法3直到控制从方法4返回后才运行。。然而,方法-3的激活帧仍可以包含“活”指针。因而,垃圾收集器142必须扫描方法-4的无暂停激活帧200(先锋激活帧)和方法-3的无暂停激活帧205(调用者激活帧)。执行扫描以识别活动指针,使得它们可以由垃圾收集过程。方法-4又可能调用其他方法,例如方法-5,而方法-5又调用方法-6。垃圾收集器142相应地将活动对象重新定位到连续的位置,以便可以将在活动对象之间找到的未使用对象合并为单个大的空闲段。这使得随后的存储器分配操作更加有效。进一步,应当注意,在上述场景中,当方法-4调用方法-5(其调用方法-6)时,方法-4不再是“当前”方法,因为方法-6是当前方法。方法-4仍然是先锋方法,因为它是堆栈扫描中的“最前面的”方法。从先锋方法调用的其他方法不需要被扫描。虽然已经扫描了先锋方法的帧,但是先锋方法仍然参与扫描。

如本文所描述的,对应于方法-5和方法-6的无暂停激活帧530将不被扫描,因为它们是在抢占点之后发起的,在这种情况下,抢占点是方法-4的调用。在本实例中,垃圾收集器142从堆栈114的底部开始扫描,先是方法-1的无暂停激活帧,接着是方法-2的无暂停激活帧(510)。同时,当控制从先锋方法返回时,进程线程负责扫描属于作为先锋方法的调用者的方法的任何先前未扫描的激活帧。如果先锋方法在垃圾收集器142扫描方法-3的激活帧之前返回,则方法-3的无暂停激活帧205由——当先锋方法返回到在其调用者的激活帧482的LRSave字段220中表示的地址时控制流到的——跳转子例程(图6)扫描。或者,在进程线程从先锋方法返回之前,垃圾收集器可以扫描方法-3的激活帧452。如果到进程线程从先锋方法返回时,垃圾收集器142已经扫描了方法-3的无暂停激活帧205,则进程线程不再次执行扫描。当发现这种情况时,无暂停激活帧的并行扫描被视为完成。

由垃圾收集器142扫描无暂停激活帧包括针对所扫描的每个激活帧找到当前活动指针。返回参见图4,在434处,垃圾收集器142通过从调用者的激活帧205获取InvokedMethodImplementation210的值来找到描述激活帧的PointerVariablePreemptionSaveArea的当前状态的MethodImplementation对象,从而找到无暂停激活帧200的活动指针。无暂停激活帧205中的InvokedMethodImplementation字段210存储描述由方法-3最近调用的方法的MethodImplementation对象的地址。此外,在434,将先锋方法的无暂停激活帧200的LRSave字段220的值与存储在MethodImplementation对象内的信息结合使用,以确定PointerVariablePreemptionSaveArea230内的哪些槽保持该特定抢占点的活动指针。

在455,垃圾收集器142的扫描工作(450)最终与进程线程的自扫描工作相遇。如果垃圾收集器142识别出线程堆栈的所有无停顿激活帧都已被扫描,那么在455和456处,垃圾收集器142用其TrueLRSave字段220的当前内容覆写所述无暂停激活帧的LRSave字段240。此时,垃圾收集器142认为进程线程的堆栈114已被完全扫描。否则,垃圾收集器142继续扫描编程堆栈114中的其他无暂停激活帧205。通常,垃圾收集器142不能完成其当前的操作阶段,直到已经完全扫描了所有进程线程的堆栈114。

本文中描述的技术方案促进在诸如Java的计算机编程语言中的无暂停垃圾收集。无暂停垃圾收集由无暂停的激活帧来促进。无暂停激活帧在顶部包括一个固定空间,用于保存在进程线程和垃圾收集线程之间共享的局部指针值,包括MethodImplementation对象指针。进程线程在由编译器建立的抢占安全点处存储和获取局部指针值。每个方法调用都被视为抢占点。进程线程通过在从特定进程线程的先锋方法返回时扫描调用者的激活帧来帮助垃圾收集。MethodImplementation对象指针提供可以被嵌入到异常(exception)中的堆栈跟踪信息。MethodImplementation对象描述了每个抢占点处“指针变量抢占保存区”的状态。

因此,本文描述的技术方案有利于改进垃圾收集计算机编程语言,以使用基于增量堆栈扫描的无暂停垃圾收集来实现高性能、时间关键的应用。通过使用如本文所述的无暂停的激活帧来执行无暂停垃圾收集,本文所述的技术方案有助于基本上在传统线程的10%内的时间关键的应用程序线程性能,并且可以实现低至10μs的抢占延迟。

本技术方案可以是处于任何可能的集成技术细节水平的系统、方法和/或计算机程序产品。计算机程序产品可包括其上具有用于使处理器执行本技术方案的各方面的计算机可读程序指令的计算机可读存储介质(或多个介质)。

计算机可读存储介质可以是可以保留和存储指令以供指令执行设备使用的有形设备。计算机可读存储介质可以是例如但不限于电子存储设备、磁存储设备、光存储设备、电磁存储设备、半导体存储设备或前述各项的任何合适的组合。计算机可读存储介质的更具体例子的非穷举列表包括以下:便携式计算机盘,硬盘、随机存取存储器(RAM)、只读存储器(ROM)、可擦除可编程只读存储器(EPROM或闪存),静态随机存取存储器(SRAM)、便携式致密盘只读存储器(CD-ROM),数字通用盘(DVD)、记忆棒、软盘、机械编码设备(诸如穿孔卡片)或具有记录在其上的指令的凹槽中的凸起结构),以及上述的任意合适的组合。如本文中所使用的计算机可读存储介质不应被解释为瞬态信号本身,诸如无线电波或其他自由传播的电磁波、通过波导或其他传输介质传播的电磁波(例如,通过光纤电缆的光脉冲)、或通过导线传输的电信号。

本文所述的计算机可读程序指令可从计算机可读存储介质下载到相应的计算/处理设备,或经由网络(例如,互联网、局域网、广域网和/或无线网络)下载到外部计算机或外部存储设备。网络可以包括铜传输电缆、光传输光纤、无线传输、路由器、防火墙、交换机、网关计算机和/或边缘服务器。每个计算/处理设备中的网络适配器卡或网络接口从网络接收计算机可读程序指令并且转发这些计算机可读程序指令以便存储在对应的计算/处理设备内的计算机可读存储介质中。

用于执行本技术方案的操作的计算机可读程序指令可以是汇编指令,指令集架构(ISA)指令、机器指令、机器相关指令、微代码、固件指令、状态设置数据,集成电路的配置数据,或以一种或多种编程语言的任何组合编写的源代码或目标代码,包括面向对象的Smalltalk、C++等编程语言,以及过程式编程语言,例如“C”编程语言或类似的编程语言。计算机可读程序指令可完全在用户”的计算机上执行、部分在用户”的计算机上执行、作为独立软件包执行、部分在用户”的计算机上部分在远程计算机上执行、或者完全在远程计算机或服务器上执行。在后一种情形中,远程计算机可以通过任何类型的网络(包括局域网(LAN)或广域网(WAN))连接到用户的计算机,或者可以连接到外部计算机(例如,通过使用互联网服务提供商的互联网)。在一些实施例中,电子电路(包括例如可编程逻辑电路、现场可编程门阵列(FPGA)或可编程逻辑阵列(PLA))可以通过使用计算机可读程序指令的状态信息来执行计算机可读程序指令以使电子电路个性化,以便执行本技术方案的方面。

在此参照根据技术方案的实施例的方法、装置(系统)和计算机程序产品的流程图和/或框图来描述本技术方案的各方面。应当理解,流程图和/或框图的每个方框以及流程图和/或框图中各方框的组合,都可以由计算机可读程序指令来实现。

这些计算机可读程序指令可以被提供给通用计算机的处理器,专用计算机或其他可编程数据处理装置,以产生机器,其通过计算机或其他可编程数据处理装置的处理器执行,创建用于实现在流程图和/或方框图的一个或多个方框中指定的功能/动作的装置。这些计算机可读程序指令还可存储在可指导计算机的计算机可读存储介质中,可编程数据处理装置,和/或以特定方式起作用的其他设备,使得具有存储在其中的指令的计算机可读存储介质包括制品,该制品包括实现流程图和/或框图中的一个或多个方框中规定的功能/动作的各方面的指令。

计算机可读程序指令还可以加载到计算机、其他可编程数据处理装置上,或使得在计算机上执行一系列操作步骤的其他装置,其他可编程装置或其他设备,以产生计算机实现的过程,使得在计算机上执行的指令,其他可编程装置或其他设备实现流程图和/或框图中的一个或多个方框中指定的功能和动作。

附图中的流程图和框图示出了根据本技术方案的不同实施例的系统、方法和计算机程序产品的可能实现的体系架构、功能和操作。对此,流程图或框图中的每个方框可以代表模块、段或指令的一部分,其包括用于实现规定的逻辑功能的一个或多个可执行指令。在一些替代实施例中,框中所标注的功能可以不以图中所标注的次序发生。例如,取决于所涉及的功能,连续示出的两个框实际上可以基本上同时执行,或者这些框有时可以以相反的顺序执行。还将注意的是,框图和/或流程图中的每个框、以及框图和/或流程图中的框的组合可以由基于专用硬件的系统来实现,所述基于专用硬件的系统执行指定的功能或动作或执行专用硬件与计算机指令的组合。

第二动作可以说是“响应”第一动作,而与第二动作是直接还是间接地由第一动作产生无关。第二动作可以在比第一动作实质上晚的时间发生,并且仍然是对第一动作的响应。类似地,即使介入动作发生在第一动作和第二动作之间,并且即使一个或多个介入动作直接导致第二动作被执行,第二动作也可以说是对第一动作的响应。例如,如果第一动作了设置标记,并且标记一旦设置后,第三动作稍后就发起第二动作,则可以说第二动作响应于第一动作。

为了阐明使用并特此通知公众,短语“,…和中的至少一个”或“,…中的至少一个或其组合”或“,…和/或”,应以最广义的方式解释,除非明确相反地声明,否则取代在上文或下文中的任何其他隐含定义,意指选自包括A、B、…和N的组的一个或多个元素。换言之,短语意指元素A、B、…或N中的一个或多个的任何组合,包括单独的任何一个元素或者一个元素与其他元素中的一个或多个的组合,所述其他元素还可以包括未列出的附加元素的组合。

还将理解,本文例示的执行指令的任何模块、单元、组件、服务器、计算机、终端或装置可包含或以其他方式存取计算机可读介质,例如存储介质、计算机存储介质或例如磁盘、光盘或磁带等数据存储装置(可移动和/或不可移动)。计算机存储介质可包括以用于存储诸如计算机可读指令、数据结构、程序模块或其他数据等信息的任何方法或技术实现的易失性和非易失性、可移动和不可移动介质。这样的计算机存储介质可以是设备的一部分或者可访问或可连接到设备。本文描述的任何应用或模块可使用可由这样的计算机可读介质存储或以其他方式保持的计算机可读/可执行指令来实现。

相关技术
  • 表示用于无暂停垃圾收集的激活帧的方法和装置
  • 确定用于移动站收发器的具有减少或者暂停的传输的帧的测量配置的装置和方法
技术分类

06120112196821