Chromium Code Reviews| Index: src/runtime-profiler.cc |
| =================================================================== |
| --- src/runtime-profiler.cc (revision 5952) |
| +++ src/runtime-profiler.cc (working copy) |
| @@ -68,12 +68,18 @@ |
| }; |
| +enum SamplerState { |
| + IN_NON_JS_STATE = 0, |
| + IN_JS_STATE = 1 |
| +}; |
| + |
| + |
| // Optimization sampler constants. |
| static const int kSamplerFrameCount = 2; |
| static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 }; |
| static const int kSamplerWindowSize = 16; |
| -static const int kSamplerTicksDelta = 32; |
| +static const int kSamplerTicksBetweenThresholdAdjustment = 32; |
| static const int kSamplerThresholdInit = 3; |
| static const int kSamplerThresholdMin = 1; |
| @@ -88,7 +94,12 @@ |
| static int sampler_threshold = kSamplerThresholdInit; |
| static int sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; |
| +static int sampler_ticks_until_threshold_adjustment = |
| + kSamplerTicksBetweenThresholdAdjustment; |
| +// The ratio of ticks spent in JS code in percent. |
| +static int js_ratio; |
| + |
| // The JSFunctions in the sampler window are not GC safe. Old-space |
| // pointers are not cleared during mark-sweep collection and therefore |
| // the window might contain stale pointers. The window is updated on |
| @@ -267,16 +278,49 @@ |
| it.Advance()) { |
| JavaScriptFrame* frame = it.frame(); |
| JSFunction* function = JSFunction::cast(frame->function()); |
| - int function_size = function->shared()->SourceSize(); |
| - int threshold_size_factor; |
| - if (function_size > kSizeLimit) { |
| - threshold_size_factor = sampler_threshold_size_factor; |
| + |
| + // Adjust threshold each time we have processed |
| + // a certain number of ticks. |
| + if (sampler_ticks_until_threshold_adjustment > 0) { |
| + sampler_ticks_until_threshold_adjustment--; |
| + if (sampler_ticks_until_threshold_adjustment == 0) { |
| + // If the threshold is not already at the minimum |
| + // modify and reset the ticks until next adjustment. |
| + if (sampler_threshold > kSamplerThresholdMin) { |
| + sampler_threshold -= kSamplerThresholdDelta; |
| + sampler_ticks_until_threshold_adjustment = |
| + kSamplerTicksBetweenThresholdAdjustment; |
| + } |
| + } |
| + } |
| + |
| + // Do not record non-optimizable functions. If the function |
| + // is not marked for recompilation, move on to the next frame. |
| + if (!IsOptimizable(function)) { |
| + if (!function->IsMarkedForLazyRecompilation()) continue; |
| } else { |
| - threshold_size_factor = 1; |
| + samples[count++] = function; |
| } |
| + int function_size = function->shared()->SourceSize(); |
| + int threshold_size_factor = (function_size > kSizeLimit) |
| + ? sampler_threshold_size_factor |
| + : 1; |
| + |
| int threshold = sampler_threshold * threshold_size_factor; |
| - samples[count++] = function; |
| + |
| + // Adjust threshold depending on the ratio of time spent |
| + // in JS code. |
| + if (js_ratio < 20) { |
| + // If we spent less than 20% of the time in JS, code |
|
Kasper Lund
2010/12/09 11:51:51
spent => spend
Karl Klose
2010/12/09 12:49:32
Done.
|
| + // do not optimize. |
| + if (!function->IsMarkedForLazyRecompilation()) continue; |
| + } else if (js_ratio < 75) { |
| + // Below 75% of time spent in JS code, only optimize very |
| + // frequently used functions. |
| + threshold *= 3; |
| + } |
| + |
| if (function->IsMarkedForLazyRecompilation()) { |
|
Kasper Lund
2010/12/09 11:51:51
Can't you just move this code up to the !IsOptimiz
Karl Klose
2010/12/09 12:49:32
Done.
|
| Code* unoptimized = function->shared()->code(); |
| int nesting = unoptimized->allow_osr_at_loop_nesting_level(); |
| @@ -284,10 +328,8 @@ |
| int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker); |
| unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting); |
| } else if (LookupSample(function) >= threshold) { |
| - if (IsOptimizable(function)) { |
| - Optimize(function, false, 0); |
| - CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function)); |
| - } |
| + Optimize(function, false, 0); |
| + CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function)); |
| } |
| } |
| @@ -341,6 +383,8 @@ |
| void RuntimeProfiler::Reset() { |
| sampler_threshold = kSamplerThresholdInit; |
| + sampler_ticks_until_threshold_adjustment = |
| + kSamplerTicksBetweenThresholdAdjustment; |
| sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; |
| } |
| @@ -360,6 +404,23 @@ |
| } |
| +static void AddStateSample(SamplerState current_state) { |
| + static const int kStateWindowSize = 128; |
| + static SamplerState state_window[kStateWindowSize]; |
| + static int state_window_position = 0; |
| + static int state_counts[2] = { kStateWindowSize, 0 }; |
| + |
| + SamplerState old_state = state_window[state_window_position]; |
| + state_counts[old_state]--; |
| + state_window[state_window_position] = current_state; |
| + state_counts[current_state]++; |
| + ASSERT(IsPowerOf2(kStateWindowSize)); |
| + state_window_position = (state_window_position + 1) & |
| + (kStateWindowSize - 1); |
| + js_ratio = state_counts[IN_JS_STATE]*100 / kStateWindowSize; |
|
Kasper Lund
2010/12/09 11:51:51
Spaces around *. Consider changing the type of js_
Karl Klose
2010/12/09 12:49:32
Done.
|
| +} |
| + |
| + |
| bool RuntimeProfilerRateLimiter::SuspendIfNecessary() { |
| static const int kNonJSTicksThreshold = 100; |
| // We suspend the runtime profiler thread when not running |
| @@ -369,8 +430,10 @@ |
| !CpuProfiler::is_profiling() && |
| !(FLAG_prof && FLAG_prof_auto)) { |
| if (Top::IsInJSState()) { |
| + AddStateSample(IN_JS_STATE); |
| non_js_ticks_ = 0; |
| } else { |
| + AddStateSample(IN_NON_JS_STATE); |
| if (non_js_ticks_ < kNonJSTicksThreshold) { |
| ++non_js_ticks_; |
| } else { |