设为首页 加入收藏

TOP

Ruby 2.2 的增量垃圾收集机制(二)
2015-07-16 12:55:45 来源: 作者: 【 】 浏览:11
Tags:Ruby 2.2 增量 垃圾 收集 机制
怨minor GC的中断时间。增量垃圾收集器的最大中断时间要小于minor GC的中断时间。如果你在minior GC不存在中断时间问题,就不用担心major GC的中断时间。


我还介绍过为Ruby实现增量垃圾收集器的一人小技巧。我们得到一系列“黑色非保护”类。为了快速执行垃圾清理,我们准备了一个非保护的bitmap代表非保护类,一个独立的已标记bitmap代表已标记类。使用两个bitmaps的逻辑可以获取“黑色非保护”类。


增量垃圾收集器中断时间评测


为了计量垃圾收集器产生在的中断时间,让我们使用?gc_tracergem. gc_tracer gem引用了 GC::Tracer模块在垃圾收集事件中获取相关参数。gc_tracergem将每个参数都保存在文件中。


垃圾收集事件包括以下事件:


如我前面所解释,Ruby的垃圾收集包含两个阶段:“标记附件”和“清理”阶段。“开始“是”开始标记附件“事件,”标记结束“是”标记附件结束“事件,”标记结束“也现时意味着”开始清理阶段",当然“清理结束”代表”清理阶段“结束,也意味着垃圾清理过程的结束。


”创建对象“和”释放对象”很容易理解:对象分配和对象释放事件。


我们通过“进入”和“离开”事件计量中断时间。增量垃圾收集(增量标记和延迟清理)引入中断标记和清理阶段。“进入“是”进入垃圾清理“???件,”离开“是”离开垃圾清理“事件。?


下图显示了当前增量垃圾收集器的事件时间。


Ruby 2.2 的增量垃圾收集机制


垃圾收集器事件


我们可以计量每一个事件的当前时间(在 Linux 上当前时间是通过 gettimeofday() 获得)。所以我们可以通过“进入”和“离开”事件计量垃圾收集器的中断时间。


我使用?ko1-test-app?做为我们中断时间的基准。ko1-test-app 是我们的一个英雄“Aaron Patterson"为我写的一个小的 rails app


为了使用 gc_tracer,我添加了一条命名为“test_gc_tracer”的规则,如下:


diff --git a/perf.rake b/perf.rake
index f336e33..7f4f1bd 100644
--- a/perf.rake
+++ b/perf.rake
@@ -54,7 +54,7 @@ def do_test_task app
? body.close
?end
?
-task :test do
+def test_run
? app = Ko1TestApp::Application.instance
? app.app
?
@@ -67,6 +67,22 @@ task :test do
? }
?end
?
+task :test do
+? test_run
+end
+
+task :test_gc_tracer do
+? require 'gc_tracer'
+? require 'pp'
+? pp GC.stat
+? file = "log.#{Process.pid}"
+? GC::Tracer.start_logging(file, events: %i(enter exit), gc_stat: false) do
+ test_run
+? end
+? pp GC.stat
+? puts "GC tracer log: #{file}"
+end
+
?task :once do
? app = Ko1TestApp::Application.instance
? app.app


运行 bundle exec rake test_gc_tracer KO1TEST_CNT=30000。我们通过数值“30000”指定模拟30,000个请求。我们可以在文件“log.xxxx”里得到结果(xxxx是程序的进程ID)。文件如下


type? tick? major_by? ? ? gc_by? have_finalizer? immediate_sweep state
enter? 1419489706840147? ? ? 0? ? newobj? 0? ? 0? ? sweeping
exit? 1419489706840157? ? ? 0? ? newobj? 0? ? 0? ? sweeping
enter? 1419489706840184? ? ? 0? ? newobj? 0? ? 0? ? sweeping
exit? 1419489706840195? ? ? 0? ? newobj? 0? ? 0? ? sweeping
enter? 1419489706840306? ? ? 0? ? newobj? 0? ? 0? ? sweeping
exit? 1419489706840313? ? ? 0? ? newobj? 0? ? 0? ? sweeping
enter? 1419489706840612? ? ? 0? ? newobj? 0? ? 0? ? sweeping
...


在我的环境下,这里有 1,142,907 行。


“type”列是事件类型,tick 是当前时间(gettimeofday()的输出结果,epoc总时间,单位是毫秒)。通过这些信息我们可以获取垃圾收集器的中断时间。通过前两行我们可以计算出中断时间为10 微秒 (1419489706840157 - 1419489706840147)。


以下小脚本显示每次中断时间。


enter_tick = 0
open(ARGV.shift){|f|
? f.each_line{|line|
? e, tick, * = line.split(/\s/)
? case e
? when 'enter'
? ? enter_tick = tick.to_i
? when 'exit'
? ? st = tick.to_i - enter_tick
? ? puts st if st > 100 # over 100 us
? else
? ? # puts line
? end
? }
}


这里有很多行,这个脚本打印了 100 微秒内的中断次数。


下图显示了统计结果


Ruby 2.2 的增量垃圾收集机制


在分代垃圾收集器中产生了7个较大的中断时间,他们应该是由“major GC”产生的。最大中断时间大概15毫秒(15Kus),不管怎样,增量垃圾收集器减少了最大中断时间(差不多2ms(2Kus)),太好了。


Ruby 2.2 通过引入增量垃圾收集算法缩短了垃圾收集的中断时间。


请注意,增量垃圾收集器不是一个银弹。我曾解释过增量垃圾收集并不改善“吞吐量”,这意味着如果请求很长并产生多个 major GC,反应时间并不会得到有效改善。使用增量垃圾收集器并不会缩短总的中断时间。


请在 Heroku 尝试你的应用,期待你的挑战!


英文原文:Incremental Garbage Collection in Ruby 2.2


首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android WebView使用深入浅出 下一篇Struts2中非表单标签的使用 compo..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: