专利名称:基于Java虚拟机的并发垃圾收集器的调度器的制作方法
技术领域:
本发明属于Java虚拟机垃圾回收技术领域,具体涉及一种基于Java虚拟机的并 发垃圾回集器的调度器。
背景技术:
随着Java等高级编程语言的兴起,如何合理的利用内存成为了为各高级语言提供环 境支持时最关键的考虑因素之一。作为内存利用的主要手段,垃圾收集技术在系统安全 和资源管理方面扮演着越来越重要的角色。随着现代应用程序使用内存量增大、对象数量增多,以及消减“停止世界”垃 圾收集所造成的停顿严重影响了应用程序的响应时间,并发的垃圾收集(Concurrent GC) 出现了。该技术使垃圾收集器可以在应用程序线程执行的情况下进行垃圾收集,即垃圾 收集器和应用程序线程是并行执行的。通过测试,并发垃圾收集技术较之“停止世界” 垃圾收集有明显的运行效率提升,所以这个概念开始为越来越多的人所接受。然而对于并发垃圾收集器何时被触发就成了一个问题因为如果垃圾收集发生 在系统内存还很空余的时候,就没有充分利用系统内存资源并且造成垃圾收集的频率过 高,反而会影响应用程序性能;如果发生在系统内存已经比较紧张的时候,那系统堆内 存就很可能在并发垃圾收集完成前被耗尽,这样就迫使垃圾收集器进行“耗尽处理”, 需要被迫把应用程序停下来,这样无疑就增加了应用程序的停顿时间。尤其对于内存需 求量大的程序,并发垃圾收集的调度方式对其运行的稳定性和效率都会有显著的影响。 所以如何恰如其分的找出这个GC触发的时间点变得十分关键。当然,对于常规的垃圾 收集技术(如“停止世界”垃圾收集),好的调度方式也能明显改善垃圾回收器的运行效 率。
发明内容
本发明的目的在于设计一种能使并发垃圾收集器在合适的时间点被触发,以便 提升垃圾收集器乃至整个程序运行效率的,关于并发垃圾收集器的调度器,并使用调度 器对垃圾收集线程进行动态调度,从而更有效的利用系统资源。本发明主要通过动态地对当前应用程序的运行情况进行分析,让垃圾收集过程 能在合适的时间点触发。在垃圾收集器的实现中,我们把当前堆内存空间占用量,应用 程序分配内存速度等因素都记录下来,以计算的方式估计出垃圾收集器的合适触发点。首先定义理想的GC触发时间点,即在垃圾收集器的跟踪处理全部完成后,清理 处理尚未开始前系统的内存资源正好完全耗尽。但是显然的,由于并发垃圾收集器是和 应用程序同时执行的,程序运行的不确定性决定了并发垃圾收集器达到理想GC触发点是 不可能的,不过我们还是可以通过评估的方式使调度器选定的GC触发点尽量的接近这一
iMuM ;^vs O在本发明中,调度器需要记录的系统的信息主要包括堆的总体大小Μ。当前堆 (Heap)内的内存消耗情况Mp当前应用程序的内存消耗的平均速率V1,以及当前垃圾收集器跟踪处理的平均速率v2。而最理想的情况是当垃圾收集的跟踪处理需要的时间、和 应用程序最后耗尽系统内存资源的时间t2相同。根据上述条件,我们可以得到以下三个 等式
t! = t2 ; ①
ti = M1ZV2 ;②
I2=(M0-M1)ZV1;; ③
根据以上三个等式,我们就可以计算出最佳的GC触发点,即每当系统的内存消耗到 M2时,[M2 = MJV2/(V1+V2)],就应该触发垃圾收集器进行工作,因为这样在垃圾收集 的跟踪处理结束时,系统的内存正好被耗尽,即得到完全的使用。也就是说,在理论上 讲这样能尽可能的逼近最优的GC触发点。然而在实际运行时,由于并发程序的不确定 性,这样的设置很可能会让系统内存资源在GC跟踪处理尚未结束时就耗尽。这时一旦 系统资源耗尽,垃圾收集器就要被迫停止应用程序来处理,这样反而会使应用程序的运 行效率减低。调度器用一个内存使用上线M'来代替堆的总大小Mtl来解决这个问题。经 过实际的测试,我们的调度器用堆总大小的90%来做内存使用上线, M* = 0.9 * M0④
所以,调度器最终的最佳GC触发点是 M+=0.9*MQ*V2/ (V1 + V2)。⑤
但是系统真的实时都检验上述数据会对性能造成显著的影响。所以本发明中的调度 器只在每次系统要求申请新的内存时才会进行上述检验,这样就能很好的减少了实时检 验带来的性能影响。当然,这样的处理同样可以满足垃圾收集器的正确性。因为只有当 应用程序申请系统内存时,系统的堆内存才会增大,其他事件不会造成系统堆内存变化。另一方面,为了在不丢失准确性的前提下尽量减小对应用程序运行的影响,调 度器在应用程序每次申请内存时都使用一个简单的时间推算方法来判断是否需要触发垃 圾收集。最后,虽然调度器可以大大降低系统资源耗尽的可能性,但是考虑到并发垃圾收集器的GC线程是和应用程序同时运行的,由并发垃圾收集的跟踪和标记等操作所需时 间的不确定性,系统资源还是有耗尽的可能。所以调度器同时也需要处理系统内存资源 耗尽的情况,调度器同样也给出了处理资源耗尽的处理方案。本发明的有益效果是本发明作为并发垃圾收集统一框架的一部分(状态 ⑥),提供了一种低开销高性能的垃圾收集调度器,优化了垃圾收集的触发点,既提高 了垃圾收集器的运行效率,也大大降低了系统资源耗尽发生的可能性。同时,该调度器 也处理了并发垃圾收集时系统资源耗尽的情况。
图1所示为并发垃圾收集的状态转换。图2所示为二分逼近法的实现过程。
具体实施例方式本发明的基本思想是通过动态收集系统实时信息,并通过进行计算出综合评估值的方式来评估出更为准确GC触发点。这里将对调度器需要收集的信息和如何综合评 估计算进行详细的讨论。1)首先定义理想的GC触发点,即在垃圾收集器的跟踪处理全部完成后,清理 处理尚未开始前系统的内存资源正好完全耗尽。但是显然的,由于并发垃圾收集器是和 应用程序同时执行的,程序运行的不确定性决定了并发垃圾收集器达到理想GC触发点是 不可能的,不过我们还是可以通过评估的方式使调度器选定的GC触发点尽量的接近这一
iMuM ;^vs O在本发明中,调度器需要记录的系统的信息主要包括堆的总体大小Μ。当前堆 (Heap)内的内存消耗情况Mp当前应用程序的内存消耗的平均速率V1,以及当前垃圾收 集器跟踪处理的平均速率V2。而最理想的情况是当垃圾收集的跟踪处理需要的时间、和 应用程序最后耗尽系统内存资源的时间t2相同。根据上述条件,我们可以得到以下三个 等式
t! = t2 ; ① ti = M1ZV2 ;②
t2 = (M0 - M1)/V1 ;③
根据以上三个等式,我们就可以计算出最佳的GC触发点,即每当系统的内存消耗到 M2时,[M2 = MJV2/(V1+V2)],就应该触发垃圾收集器进行工作,因为这样在垃圾收集 的跟踪处理结束时,系统的内存正好被耗尽,即得到完全的使用。也就是说,在理论上 讲这样能尽可能的逼近最优的GC触发点。然而在实际运行时,由于并发程序的不确定 性,这样的设置很可能会让系统内存资源在GC跟踪处理尚未结束时就耗尽。这时一旦 系统资源耗尽,垃圾收集器就要被迫停止应用程序来处理,这样反而会使应用程序的运 行效率减低。调度器用一个内存使用上线M'来代替堆的总大小Mtl来解决这个问题。经 过实际的测试,我们的调度器用堆总大小的90%来做内存使用上线, M* = 0.9 * M0④
所以,调度器最终的最佳GC触发点是 M+=0.9*MQ*V2/ (V1 + V2)。⑤
但是系统真的实时都检验上述数据会对性能造成显著的影响。所以本发明中的调度 器只在每次系统要求申请新的内存时才会进行上述检验,这样就能很好的减少了实时检 验带来的性能影响。当然,这样的处理同样可以满足垃圾收集器的正确性。因为只有 当应用程序申请系统内存时,系统的堆内存才会增大,其他事件不会造成系统堆内存变 化。2)为了进一步提高应用程序的运行效率,我们对调度器做了进一步的优化。不 难看出,其实在每次应用程序请求内存时都检验是否要求进行垃圾收集还是有相当的冗 余判断,例如在一次垃圾收集刚结束时,系统剩余内存应该很充裕,这时候的检验操作 就是冗余的。而跟踪扫描整个堆内存的情况的开销是不能忽略的,针对这种情况,调度 器以一个简单的时间推算来代替堆内存的扫描,从而大大减小了开销。这个时间推算的基本思想是利用之前收集的当前系统内存使用量和应用程序消 耗内存的速率来打制的推算出下一次需要进行垃圾收集的时间。如在一次垃圾收集结束 时(假设当前时间是υ,根据垃圾收集结束时堆内存的剩余情况Μ和应用程序消耗内存的平均速率V,那么我们就能推算出下一次发生GC的时间大致为t1; 而 I1 = t0 + M/V⑥
调度器认为在to到^这个时间端间的内存申请都是合法的,不对其进行对检验。这 样调度器就大大减少了冗余的检验次数,从而进一步提高应用程序的运行效率。 和1)中需要确定内存使用上限同样的,如果真的简单的用式⑥中计算的、来作 为下一次的垃圾收集时间触发点,很可能在垃圾收集结束之前系统的内存已经耗尽了。 这样就要求垃圾收集器额外地处理系统耗尽的情况,反而影响了应用程序的运行效率。 所以在实际实现时,调度器会采取一些保守策略来慢慢的逼近下次垃圾回收的时间点。 这样的保守算法有很多,核心思想都是以多进行几次对扫描为代价,来避免系统内存资 源的耗尽。这里介绍下实现较为简单也较为直观的二分逼近法。二分逼近法的原理图见图2,调度器现在就用这种方法来逼近GC触发点。像上 述情况中一样,调度器还是在每次垃圾收集结束时,重新检测堆内存的情况,记录下垃 圾收集结束后堆内存的剩余情况Mtl和应用程序消耗内存的平均速率V—不同于前者的 是为了防止出现应用程序大量消耗内存资源而使系统提前资源耗尽的情况发生,调度器 采用二分接近的,
即第一次选取的t/为
t/ = t0 + M0/2V0⑦
而第二次选取的t2'为
t2' = / +M1/2V10⑧
不难从式⑦和式⑧看出,调度器在有以下的迭代方式(式⑨)来逼近最终的GC触发 点,而只有当当前tn+1 ’时刻的内存消耗量超过了 1)中介绍的内存上线值时,迭代就终 止,开始进行垃圾收集工作。这样的做法较好的避免了在进行垃圾收集之前或之中系统 发生资源耗尽的情况,因为调度器在每个GC触发点理论时间进行到一半处就进行检验, 这样有利于避免应用程序在某一时间段中大量消耗内存带来的影响。tn+1' =t; +Mn/2Vn。⑨
(注在以上各式中,Mtl表示、时刻堆的大小,Vtl表示、时刻内存消耗的平均速 率,以此类推,Mn表示、时刻堆的大小,Vn表示tn时刻内存消耗的平均速率。)
如图2中所示,在某一次垃圾结束时刻to,调度器用式⑨计算出^时刻,之后忽略、 到、时间段中对堆内存的申请的检验。当到达^时刻时,首先检验是否已经超过了需要 进行垃圾收集的堆内存使用上限,若还没有超过,继续用式⑨迭代计算t2,^等;若已经 超过,如图中的^时刻,这样就停止迭代过程,开始进行垃圾收集工作。经过实验测得,一般用二分法来逼近GC触发点需要进行5 8次迭代,也就是说 只要进行5 8次对堆内存的整体扫描。而用原先的每次分配内存时就进行检验,两次垃 圾收集过程之间的扫描对内存次数可能就是上百甚至上千次。所以调度器以时间推算来 减少冗余扫描对应用程序的运行效率有很大的积极意义。3)这一部分将要介绍调度器对系统内存资源耗尽的回复策略。上述2)中提到 的时间推算方法虽然对应用程序的运行效率,但是因为省略了很多对申请内存的验证, 所以对于内存消耗量很不稳定的应用程序来说在提升运行效率的同时这样的处理又增加 了系统内存资源耗尽的可能性。所以这里对系统内存资源耗尽的处理的好坏就变的更加重要了。对于一个成熟的并行垃圾回收器而言,系统内存资源耗尽处理,本身就是一个 重要的单独模块,而我们实现的调度器把系统资源耗尽处理集成到调度器中,使并发垃 圾收集器的触发与灾难处理都由调度器来完成。下面就简单的说说系统资源耗尽处理的 实现思想。 按照系统资源耗尽发生的时刻段,可以把耗尽情况分成3种 a)发生在应用程序运行中,垃圾收集线程没有启动。b)发生在垃圾收集线程启动后的跟踪阶段。c)发生在垃圾收集线程启动后的收集清理阶段。从应用程序的运行效率最大化的角度考虑,调度器利用并发垃圾收集的特点, 对这三种情况分别进行了处理。a)对于第一种情况,因为垃圾收集线程还没有启动,没有可以利用的信息,所 以只能把所有的线程都停下来,做一次“停止世界”的垃圾收集过程。之后再让程序继 续运行。b)当系统资源耗尽出现在垃圾收集线程启动后的跟踪阶段,那么并发垃圾收集 阶段的跟踪信息时可以复用的。调度器的做法是停掉其他应用程序的线程,让垃圾收集 线程把跟踪阶段完成,先得到对象跟踪信息。之后用这个对象跟踪信息做一次“停止世 界”的垃圾收集过程来释放内存。这样就省去了一次跟踪处理。c)对于系统资源耗尽出现在垃圾收集线程启动后的收集清理阶段,处理就更为 简单了。因为之前的跟踪和清理过程都还是适用的,调度只要停掉其他应用程序的线 程,让垃圾收集线程把收集清理阶段完成就可以了。
权利要求
1.一种基于Java虚拟机的并发垃圾收集器的调度器,其特征在于调度器记录系统的 信息包括堆的总体大小Mp当前堆内的内存消耗情况Mp当前应用程序的内存消耗的平 均速率V1,以及当前垃圾收集器跟踪处理的平均速率V2;且垃圾收集的跟踪处理需要的 时间^和应用程序最后耗尽系统内存资源的时间t2相同,即得到以下三个等式tl — t2 ;ti = M1ZV2 ;t2 = (M0 - M1)/V1 ;于是,调度器最终的最佳GC触发时间点为 M+i.^Mon^/OA+V》。
2.根据权利要求1所述的基于Java虚拟机的并发垃圾收集器的调度器,其特征在于所 述调度器采用二分逼近法逼近GC触发时间点,即第一次选取的时间t/为t/ = t0 + M0/2V0⑦而第二次选取的时间t2'为并按下式进行计算在以上各式中,Mtl表示、时刻堆的大小,Vtl表示、时刻内存消耗的平均速率,以此 类推,Mn表示、时刻堆的大小,Vn表示tn时刻内存消耗的平均速率;在某一次垃圾结束时刻^,调度器用式⑨计算出^时刻,之后忽略Ic^ljt1时间段中对 堆内存的申请的检验;当到达^时刻时,首先检验是否已经超过了需要进行垃圾收集的 堆内存使用上限,若还没有超过,继续用式⑨迭代计算t2,t3……;若已经超过,就停止 迭代过程,开始进行垃圾收集工作。
3.根据权利要求2所述的基于Java虚拟机的并发垃圾收集器的调度器,其特征在于所 述调度器还包括对系统资源耗尽处理按照系统资源耗尽发生的时刻段,把资源耗尽情 况分成3种a)发生在应用程序运行中,垃圾收集线程没有启动;b)发生在垃圾收集线程启动后的跟踪阶段;c)发生在垃圾收集线程启动后的收集清理阶段;调度器利用并发垃圾收集的特点,对这三种情况分别进行如下处理a)对于第一种情况,只把所有的线程都停下来,做一次“停止世界”的垃圾收集过 程,之后再让程序继续运行;b)当系统资源耗尽出现在垃圾收集线程启动后的跟踪阶段,那么并发垃圾收集阶段 的跟踪信息予以复用;调度器停掉其他应用程序的线程,让垃圾收集线程把跟踪阶段完 成,先得到对象跟踪信息;之后用这个对象跟踪信息做一次“停止世界”的垃圾收集过 程来释放内存;c)对于系统资源耗尽出现在垃圾收集线程启动后的收集清理阶段,调度器停掉其他 应用程序的线程,让垃圾收集线程把收集清理阶段完成。
全文摘要
发明属于Java虚拟机垃圾回收技术领域,具体为一种基于Java虚拟机的并发垃圾回集器的调度器。本发明调度器主要通过动态地对当前应用程序的运行情况进行分析,让垃圾收集过程能在合适的时间点触发。调度器在应用程序每次申请内存时都使用一个简单的时间推算方法来判断是否需要触发垃圾收集。调度器同时也处理系统内存资源耗尽的情况。本发明作为并发垃圾收集统一框架的一部分,提供了一种低开销高性能的垃圾收集调度器,优化了垃圾收集的触发点,既提高了垃圾收集器的运行效率,也大大降低了系统资源耗尽发生的可能性。
文档编号G06F9/48GK102023896SQ20101059592
公开日2011年4月20日 申请日期2010年12月20日 优先权日2010年12月20日
发明者周寻, 张源, 杨珉, 王迪, 臧斌宇 申请人:复旦大学