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

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) {
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)) continue;
290 } 307 samples[count++] = function;
308
309 int function_size = function->shared()->SourceSize();
310 int threshold_size_factor = (function_size > kSizeLimit)
311 ? sampler_threshold_size_factor
312 : 1;
313
314 int threshold = sampler_threshold * threshold_size_factor;
315 int current_js_ratio = NoBarrier_Load(&js_ratio);
316
317 // Adjust threshold depending on the ratio of time spent
318 // in JS code.
319 if (current_js_ratio < 20) {
320 // If we spend less than 20% of the time in JS code,
321 // do not optimize.
322 continue;
323 } else if (current_js_ratio < 75) {
324 // Below 75% of time spent in JS code, only optimize very
325 // frequently used functions.
326 threshold *= 3;
327 }
328
329 if (LookupSample(function) >= threshold) {
330 Optimize(function, false, 0);
331 CompilationCache::MarkForEagerOptimizing(Handle<JSFunction>(function));
291 } 332 }
292 } 333 }
293 334
294 // Add the collected functions as samples. It's important not to do 335 // Add the collected functions as samples. It's important not to do
295 // this as part of collecting them because this will interfere with 336 // this as part of collecting them because this will interfere with
296 // the sample lookup in case of recursive functions. 337 // the sample lookup in case of recursive functions.
297 for (int i = 0; i < count; i++) { 338 for (int i = 0; i < count; i++) {
298 AddSample(samples[i], kSamplerFrameWeight[i]); 339 AddSample(samples[i], kSamplerFrameWeight[i]);
299 } 340 }
300 } 341 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 void RuntimeProfiler::Setup() { 375 void RuntimeProfiler::Setup() {
335 ClearSampleBuffer(); 376 ClearSampleBuffer();
336 // If the ticker hasn't already started, make sure to do so to get 377 // If the ticker hasn't already started, make sure to do so to get
337 // the ticks for the runtime profiler. 378 // the ticks for the runtime profiler.
338 if (IsEnabled()) Logger::EnsureTickerStarted(); 379 if (IsEnabled()) Logger::EnsureTickerStarted();
339 } 380 }
340 381
341 382
342 void RuntimeProfiler::Reset() { 383 void RuntimeProfiler::Reset() {
343 sampler_threshold = kSamplerThresholdInit; 384 sampler_threshold = kSamplerThresholdInit;
385 sampler_ticks_until_threshold_adjustment =
386 kSamplerTicksBetweenThresholdAdjustment;
344 sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit; 387 sampler_threshold_size_factor = kSamplerThresholdSizeFactorInit;
345 } 388 }
346 389
347 390
348 void RuntimeProfiler::TearDown() { 391 void RuntimeProfiler::TearDown() {
349 // Nothing to do. 392 // Nothing to do.
350 } 393 }
351 394
352 395
353 Object** RuntimeProfiler::SamplerWindowAddress() { 396 Object** RuntimeProfiler::SamplerWindowAddress() {
354 return sampler_window; 397 return sampler_window;
355 } 398 }
356 399
357 400
358 int RuntimeProfiler::SamplerWindowSize() { 401 int RuntimeProfiler::SamplerWindowSize() {
359 return kSamplerWindowSize; 402 return kSamplerWindowSize;
360 } 403 }
361 404
362 405
406 static void AddStateSample(SamplerState current_state) {
407 static const int kStateWindowSize = 128;
408 static SamplerState state_window[kStateWindowSize];
409 static int state_window_position = 0;
410 static int state_counts[2] = { kStateWindowSize, 0 };
411
412 SamplerState old_state = state_window[state_window_position];
413 state_counts[old_state]--;
414 state_window[state_window_position] = current_state;
415 state_counts[current_state]++;
416 ASSERT(IsPowerOf2(kStateWindowSize));
417 state_window_position = (state_window_position + 1) &
418 (kStateWindowSize - 1);
419 NoBarrier_Store(&js_ratio, state_counts[IN_JS_STATE] * 100 /
420 kStateWindowSize);
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
« 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