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

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
« no previous file with comments | « src/flag-definitions.h ('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 Atomic32 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) {
Kasper Lund 2010/12/09 13:02:37 Maybe make this <= 0 to be defensive.
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
278 int threshold = sampler_threshold * threshold_size_factor;
279 samples[count++] = function;
280 if (function->IsMarkedForLazyRecompilation()) { 297 if (function->IsMarkedForLazyRecompilation()) {
281 Code* unoptimized = function->shared()->code(); 298 Code* unoptimized = function->shared()->code();
282 int nesting = unoptimized->allow_osr_at_loop_nesting_level(); 299 int nesting = unoptimized->allow_osr_at_loop_nesting_level();
283 if (nesting == 0) AttemptOnStackReplacement(function); 300 if (nesting == 0) AttemptOnStackReplacement(function);
284 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker); 301 int new_nesting = Min(nesting + 1, Code::kMaxLoopNestingMarker);
285 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting); 302 unoptimized->set_allow_osr_at_loop_nesting_level(new_nesting);
286 } else if (LookupSample(function) >= threshold) { 303 }
287 if (IsOptimizable(function)) { 304
288 Optimize(function, false, 0); 305 // Do not record non-optimizable functions.
289 CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function)); 306 if (!IsOptimizable(function)) {
Kasper Lund 2010/12/09 13:02:37 I would put this on one line.
290 } 307 continue;
308 }
309 samples[count++] = function;
310
311 int function_size = function->shared()->SourceSize();
312 int threshold_size_factor = (function_size > kSizeLimit)
313 ? sampler_threshold_size_factor
314 : 1;
315
316 int threshold = sampler_threshold * threshold_size_factor;
317
Kasper Lund 2010/12/09 13:02:37 Remove this newline and add one below the line def
318 int current_js_ratio = NoBarrier_Load(&js_ratio);
319 // Adjust threshold depending on the ratio of time spent
320 // in JS code.
321 if (current_js_ratio < 20) {
322 // If we spend less than 20% of the time in JS code,
323 // do not optimize.
324 continue;
325 } else if (current_js_ratio < 75) {
326 // Below 75% of time spent in JS code, only optimize very
327 // frequently used functions.
328 threshold *= 3;
329 }
330
331 if (LookupSample(function) >= threshold) {
332 Optimize(function, false, 0);
333 CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function));
291 } 334 }
292 } 335 }
293 336
294 // Add the collected functions as samples. It's important not to do 337 // Add the collected functions as samples. It's important not to do
295 // this as part of collecting them because this will interfere with 338 // this as part of collecting them because this will interfere with
296 // the sample lookup in case of recursive functions. 339 // the sample lookup in case of recursive functions.
297 for (int i = 0; i < count; i++) { 340 for (int i = 0; i < count; i++) {
298 AddSample(samples[i], kSamplerFrameWeight[i]); 341 AddSample(samples[i], kSamplerFrameWeight[i]);
299 } 342 }
300 } 343 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 void RuntimeProfiler::Setup() { 377 void RuntimeProfiler::Setup() {
335 ClearSampleBuffer(); 378 ClearSampleBuffer();
336 // If the ticker hasn't already started, make sure to do so to get 379 // If the ticker hasn't already started, make sure to do so to get
337 // the ticks for the runtime profiler. 380 // the ticks for the runtime profiler.
338 if (IsEnabled()) Logger::EnsureTickerStarted(); 381 if (IsEnabled()) Logger::EnsureTickerStarted();
339 } 382 }
340 383
341 384
342 void RuntimeProfiler::Reset() { 385 void RuntimeProfiler::Reset() {
343 sampler_threshold = kSamplerThresholdInit; 386 sampler_threshold = kSamplerThresholdInit;
387 sampler_ticks_until_threshold_adjustment =
388 kSamplerTicksBetweenThresholdAdjustment;
344 sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; 389 sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit;
345 } 390 }
346 391
347 392
348 void RuntimeProfiler::TearDown() { 393 void RuntimeProfiler::TearDown() {
349 // Nothing to do. 394 // Nothing to do.
350 } 395 }
351 396
352 397
353 Object** RuntimeProfiler::SamplerWindowAddress() { 398 Object** RuntimeProfiler::SamplerWindowAddress() {
354 return sampler_window; 399 return sampler_window;
355 } 400 }
356 401
357 402
358 int RuntimeProfiler::SamplerWindowSize() { 403 int RuntimeProfiler::SamplerWindowSize() {
359 return kSamplerWindowSize; 404 return kSamplerWindowSize;
360 } 405 }
361 406
362 407
408 static void AddStateSample(SamplerState current_state) {
409 static const int kStateWindowSize = 128;
410 static SamplerState state_window[kStateWindowSize];
411 static int state_window_position = 0;
412 static int state_counts[2] = { kStateWindowSize, 0 };
413
414 SamplerState old_state = state_window[state_window_position];
415 state_counts[old_state]--;
416 state_window[state_window_position] = current_state;
417 state_counts[current_state]++;
418 ASSERT(IsPowerOf2(kStateWindowSize));
419 state_window_position = (state_window_position + 1) &
420 (kStateWindowSize - 1);
421 NoBarrier_Store(&js_ratio, state_counts[IN_JS_STATE] * 100 /
422 kStateWindowSize);
423 }
424
425
363 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() { 426 bool RuntimeProfilerRateLimiter::SuspendIfNecessary() {
364 static const int kNonJSTicksThreshold = 100; 427 static const int kNonJSTicksThreshold = 100;
365 // We suspend the runtime profiler thread when not running 428 // We suspend the runtime profiler thread when not running
366 // JavaScript. If the CPU profiler is active we must not do this 429 // JavaScript. If the CPU profiler is active we must not do this
367 // because it samples both JavaScript and C++ code. 430 // because it samples both JavaScript and C++ code.
368 if (RuntimeProfiler::IsEnabled() && 431 if (RuntimeProfiler::IsEnabled() &&
369 !CpuProfiler::is_profiling() && 432 !CpuProfiler::is_profiling() &&
370 !(FLAG_prof && FLAG_prof_auto)) { 433 !(FLAG_prof && FLAG_prof_auto)) {
371 if (Top::IsInJSState()) { 434 if (Top::IsInJSState()) {
435 AddStateSample(IN_JS_STATE);
372 non_js_ticks_ = 0; 436 non_js_ticks_ = 0;
373 } else { 437 } else {
438 AddStateSample(IN_NON_JS_STATE);
374 if (non_js_ticks_ < kNonJSTicksThreshold) { 439 if (non_js_ticks_ < kNonJSTicksThreshold) {
375 ++non_js_ticks_; 440 ++non_js_ticks_;
376 } else { 441 } else {
377 if (Top::WaitForJSState()) return true; 442 if (Top::WaitForJSState()) return true;
378 } 443 }
379 } 444 }
380 } 445 }
381 return false; 446 return false;
382 } 447 }
383 448
384 449
385 } } // namespace v8::internal 450 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/flag-definitions.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698