Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: src/runtime-profiler.cc

Issue 5633009: Collect only optimizable function samples.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/compiler.cc ('K') | « src/compiler.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 private: 61 private:
62 void Destroy(); 62 void Destroy();
63 static void WeakCallback(v8::Persistent<v8::Value> object, void* data); 63 static void WeakCallback(v8::Persistent<v8::Value> object, void* data);
64 64
65 PendingListNode* next_; 65 PendingListNode* next_;
66 Handle<Object> function_; // Weak handle. 66 Handle<Object> function_; // Weak handle.
67 int64_t start_; 67 int64_t start_;
68 }; 68 };
69 69
70 70
71 enum SamplerState {
72 IN_NON_JS_STATE = 0,
73 IN_JS_STATE = 1
74 };
75
76
71 // Optimization sampler constants. 77 // Optimization sampler constants.
72 static const int kSamplerFrameCount = 2; 78 static const int kSamplerFrameCount = 2;
73 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 }; 79 static const int kSamplerFrameWeight[kSamplerFrameCount] = { 2, 1 };
74 static const int kSamplerWindowSize = 16; 80 static const int kSamplerWindowSize = 16;
75 81
76 static const int kSamplerTicksDelta = 32; 82 static const int kSamplerTicksBetweenThresholdAdjustment = 32;
77 83
78 static const int kSamplerThresholdInit = 3; 84 static const int kSamplerThresholdInit = 3;
79 static const int kSamplerThresholdMin = 1; 85 static const int kSamplerThresholdMin = 1;
80 static const int kSamplerThresholdDelta = 1; 86 static const int kSamplerThresholdDelta = 1;
81 87
82 static const int kSamplerThresholdSizeFactorInit = 3; 88 static const int kSamplerThresholdSizeFactorInit = 3;
83 static const int kSamplerThresholdSizeFactorMin = 1; 89 static const int kSamplerThresholdSizeFactorMin = 1;
84 static const int kSamplerThresholdSizeFactorDelta = 1; 90 static const int kSamplerThresholdSizeFactorDelta = 1;
85 91
86 static const int kSizeLimit = 1500; 92 static const int kSizeLimit = 1500;
87 93
88 static int sampler_threshold = kSamplerThresholdInit; 94 static int sampler_threshold = kSamplerThresholdInit;
89 static int sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; 95 static int sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit;
90 96
97 static int sampler_ticks_until_threshold_adjustment =
98 kSamplerTicksBetweenThresholdAdjustment;
99
100 // The ratio of ticks spent in JS code in percent.
101 static int js_ratio;
91 102
92 // The JSFunctions in the sampler window are not GC safe. Old-space 103 // The JSFunctions in the sampler window are not GC safe. Old-space
93 // pointers are not cleared during mark-sweep collection and therefore 104 // pointers are not cleared during mark-sweep collection and therefore
94 // the window might contain stale pointers. The window is updated on 105 // the window might contain stale pointers. The window is updated on
95 // scavenges and (parts of it) cleared on mark-sweep and 106 // scavenges and (parts of it) cleared on mark-sweep and
96 // mark-sweep-compact. 107 // mark-sweep-compact.
97 static Object* sampler_window[kSamplerWindowSize] = { NULL, }; 108 static Object* sampler_window[kSamplerWindowSize] = { NULL, };
98 static int sampler_window_position = 0; 109 static int sampler_window_position = 0;
99 static int sampler_window_weight[kSamplerWindowSize] = { 0, }; 110 static int sampler_window_weight[kSamplerWindowSize] = { 0, };
100 111
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 // Run through the JavaScript frames and collect them. If we already 271 // Run through the JavaScript frames and collect them. If we already
261 // have a sample of the function, we mark it for optimizations 272 // have a sample of the function, we mark it for optimizations
262 // (eagerly or lazily). 273 // (eagerly or lazily).
263 JSFunction* samples[kSamplerFrameCount]; 274 JSFunction* samples[kSamplerFrameCount];
264 int count = 0; 275 int count = 0;
265 for (JavaScriptFrameIterator it; 276 for (JavaScriptFrameIterator it;
266 count < kSamplerFrameCount && !it.done(); 277 count < kSamplerFrameCount && !it.done();
267 it.Advance()) { 278 it.Advance()) {
268 JavaScriptFrame* frame = it.frame(); 279 JavaScriptFrame* frame = it.frame();
269 JSFunction* function = JSFunction::cast(frame->function()); 280 JSFunction* function = JSFunction::cast(frame->function());
270 int function_size = function->shared()->SourceSize(); 281
271 int threshold_size_factor; 282 // Adjust threshold each time we have processed
272 if (function_size > kSizeLimit) { 283 // a certain number of ticks.
273 threshold_size_factor = sampler_threshold_size_factor; 284 if (sampler_ticks_until_threshold_adjustment > 0) {
274 } else { 285 sampler_ticks_until_threshold_adjustment--;
275 threshold_size_factor = 1; 286 if (sampler_ticks_until_threshold_adjustment == 0) {
287 // If the threshold is not already at the minimum
288 // modify and reset the ticks until next adjustment.
289 if (sampler_threshold > kSamplerThresholdMin) {
290 sampler_threshold -= kSamplerThresholdDelta;
291 sampler_ticks_until_threshold_adjustment =
292 kSamplerTicksBetweenThresholdAdjustment;
293 }
294 }
276 } 295 }
277 296
297 // Do not record non-optimizable functions. If the function
298 // is not marked for recompilation, move on to the next frame.
299 if (!IsOptimizable(function)) {
300 if (!function->IsMarkedForLazyRecompilation()) continue;
301 } else {
302 samples[count++] = function;
303 }
304
305 int function_size = function->shared()->SourceSize();
306 int threshold_size_factor = (function_size > kSizeLimit)
307 ? sampler_threshold_size_factor
308 : 1;
309
278 int threshold = sampler_threshold * threshold_size_factor; 310 int threshold = sampler_threshold * threshold_size_factor;
279 samples[count++] = function; 311
312 // Adjust threshold depending on the ratio of time spent
313 // in JS code.
314 if (js_ratio < 20) {
315 // 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.
316 // do not optimize.
317 if (!function->IsMarkedForLazyRecompilation()) continue;
318 } else if (js_ratio < 75) {
319 // Below 75% of time spent in JS code, only optimize very
320 // frequently used functions.
321 threshold *= 3;
322 }
323
280 if (function->IsMarkedForLazyRecompilation()) { 324 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.
281 Code* unoptimized = function->shared()->code(); 325 Code* unoptimized = function->shared()->code();
282 int nesting = unoptimized->allow_osr_at_loop_nesting_level(); 326 int nesting = unoptimized->allow_osr_at_loop_nesting_level();
283 if (nesting == 0) AttemptOnStackReplacement(function); 327 if (nesting == 0) AttemptOnStackReplacement(function);
284 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker); 328 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker);
285 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting); 329 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting);
286 } else if (LookupSample(function) >= threshold) { 330 } else if (LookupSample(function) >= threshold) {
287 if (IsOptimizable(function)) { 331 Optimize(function, false, 0);
288 Optimize(function, false, 0); 332 CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function));
289 CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function));
290 }
291 } 333 }
292 } 334 }
293 335
294 // Add the collected functions as samples. It's important not to do 336 // Add the collected functions as samples. It's important not to do
295 // this as part of collecting them because this will interfere with 337 // this as part of collecting them because this will interfere with
296 // the sample lookup in case of recursive functions. 338 // the sample lookup in case of recursive functions.
297 for (int i = 0; i < count; i++) { 339 for (int i = 0; i < count; i++) {
298 AddSample(samples[i], kSamplerFrameWeight[i]); 340 AddSample(samples[i], kSamplerFrameWeight[i]);
299 } 341 }
300 } 342 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 void RuntimeProfiler::Setup() { 376 void RuntimeProfiler::Setup() {
335 ClearSampleBuffer(); 377 ClearSampleBuffer();
336 // If the ticker hasn't already started, make sure to do so to get 378 // If the ticker hasn't already started, make sure to do so to get
337 // the ticks for the runtime profiler. 379 // the ticks for the runtime profiler.
338 if (IsEnabled()) Logger::EnsureTickerStarted(); 380 if (IsEnabled()) Logger::EnsureTickerStarted();
339 } 381 }
340 382
341 383
342 void RuntimeProfiler::Reset() { 384 void RuntimeProfiler::Reset() {
343 sampler_threshold = kSamplerThresholdInit; 385 sampler_threshold = kSamplerThresholdInit;
386 sampler_ticks_until_threshold_adjustment =
387 kSamplerTicksBetweenThresholdAdjustment;
344 sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; 388 sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit;
345 } 389 }
346 390
347 391
348 void RuntimeProfiler::TearDown() { 392 void RuntimeProfiler::TearDown() {
349 // Nothing to do. 393 // Nothing to do.
350 } 394 }
351 395
352 396
353 Object** RuntimeProfiler::SamplerWindowAddress() { 397 Object** RuntimeProfiler::SamplerWindowAddress() {
354 return sampler_window; 398 return sampler_window;
355 } 399 }
356 400
357 401
358 int RuntimeProfiler::SamplerWindowSize() { 402 int RuntimeProfiler::SamplerWindowSize() {
359 return kSamplerWindowSize; 403 return kSamplerWindowSize;
360 } 404 }
361 405
362 406
407 static void AddStateSample(SamplerState current_state) {
408 static const int kStateWindowSize = 128;
409 static SamplerState state_window[kStateWindowSize];
410 static int state_window_position = 0;
411 static int state_counts[2] = { kStateWindowSize, 0 };
412
413 SamplerState old_state = state_window[state_window_position];
414 state_counts[old_state]--;
415 state_window[state_window_position] = current_state;
416 state_counts[current_state]++;
417 ASSERT(IsPowerOf2(kStateWindowSize));
418 state_window_position = (state_window_position + 1) &
419 (kStateWindowSize - 1);
420 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.
421 }
422
423
363 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() { 424 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
364 static const int kNonJSTicksThreshold = 100; 425 static const int kNonJSTicksThreshold = 100;
365 // We suspend the runtime profiler thread when not running 426 // We suspend the runtime profiler thread when not running
366 // JavaScript. If the CPU profiler is active we must not do this 427 // JavaScript. If the CPU profiler is active we must not do this
367 // because it samples both JavaScript and C++ code. 428 // because it samples both JavaScript and C++ code.
368 if (RuntimeProfiler::IsEnabled() && 429 if (RuntimeProfiler::IsEnabled() &&
369 !CpuProfiler::is_profiling() && 430 !CpuProfiler::is_profiling() &&
370 !(FLAG_prof && FLAG_prof_auto)) { 431 !(FLAG_prof && FLAG_prof_auto)) {
371 if (Top::IsInJSState()) { 432 if (Top::IsInJSState()) {
433 AddStateSample(IN_JS_STATE);
372 non_js_ticks_ = 0; 434 non_js_ticks_ = 0;
373 } else { 435 } else {
436 AddStateSample(IN_NON_JS_STATE);
374 if (non_js_ticks_ < kNonJSTicksThreshold) { 437 if (non_js_ticks_ < kNonJSTicksThreshold) {
375 ++non_js_ticks_; 438 ++non_js_ticks_;
376 } else { 439 } else {
377 if (Top::WaitForJSState()) return true; 440 if (Top::WaitForJSState()) return true;
378 } 441 }
379 } 442 }
380 } 443 }
381 return false; 444 return false;
382 } 445 }
383 446
384 447
385 } } // namespace v8::internal 448 } } // namespace v8::internal
OLDNEW
« src/compiler.cc ('K') | « src/compiler.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698