说我在JRuby程序中有以下循环:
loop do
x=foo()
break if x
bar()
end
并且我想仅出于bar
的调用收集性能分析信息。这该怎么做?我到现在为止:
pd = []
loop do
x=foo()
break if x
pd << JRuby::Profiler.profile { bar() }
end
[这给我留下了配置文件数据对象的数组pd
,每次调用bar
都会得到一个。是否可以通过组合所有pd
元素来创建“摘要”数据对象?甚至更好的是,有一个对象,其中profile
只会添加到现有的分析信息中?
我在Google上搜索了JRuby :: Profiler API的文档,但是除了几个简单的示例外什么都找不到,没有一个涵盖我的情况。
UPDATE:这是我尝试过的另一种尝试,也无济于事。
由于profile
方法最初清除了Profiler中的配置文件数据,所以我试图将概要分析步骤与数据初始化步骤分开,如下所示:
JRuby::Profiler.clear
loop do
x=foo()
break if x
JRuby::Profiler.send(:current_thread_context).start_profiling
bar()
JRuby::Profiler.send(:current_thread_context).stop_profiling
end
profile_data = JRuby::Profiler.send(:profile_data)
这似乎起初是可行的,但经过调查后,我发现profile_data
然后包含来自bar
的最后一次(最近)执行的概要分析信息,而不是所有收集在一起的执行中的概要信息。
我想出了一个解决方案,尽管我感觉我正在使用大量未公开的功能来使其正常工作。我还必须补充一点,我正在使用(1.7.27),因此以后的JRuby版本可能会或可能不需要其他方法。
分析的问题在于start_profiling
(对应于Java :: OrgJrubyRuntime :: ThreadContext类中的Java方法startProfiling)不仅打开了分析标志,而且还分配了一个新的ProfileData对象。我们要做的是重用旧对象。stop_profiling
OTOH仅切换配置文件开关,并不重要。
[不幸的是,ThreadContext
没有提供操纵isProfiling
切换的方法,因此,第一步,我们必须添加一个:
class Java::OrgJrubyRuntime::ThreadContext
field_writer :isProfiling
end
这样,我们可以设置/重置内部isProfiling
开关。现在我的循环变成:
context = JRuby::Profiler.send(:current_thread_context)
JRuby::Profiler.clear
profile_data_is_allocated = nil
loop do
x=foo()
break if x
# The first time, we allocate the profile data
profile_data_is_allocated ||= context.start_profiling
context.isProfiling = true
bar()
context.isProfiling = false
end
profile_data = JRuby::Profiler.send(:profile_data)
[在此解决方案中,我试图尽可能接近JRuby::Profiler
类的功能,但是我们看到,仍然唯一使用的公共方法是clear
方法。基本上,我已经根据ThreadContext
类重新实现了分析;因此,如果有人提出了更好的解决方案,我将非常感激。