Browse Source

deps: don't busy loop in v8 cpu profiler thread

Backport 6964a9e0685fa186d9d9b7907be17505e839db1a from upstream v8.

Original commit message:

  Make CPU profiler do not hog 100% of CPU.

  Tick event processor should not stay in a tight loop
  when there's nothing to do. It can go sleep until next sample event.

  LOG=N
  BUG=v8:3967
  Committed: https://crrev.com/6964a9e0685fa186d9d9b7907be17505e839db1a
  Cr-Commit-Position: refs/heads/master@{#28211}

Fixes #25137
Related: #9439, #8789

PR: #25268
PR-URL: https://github.com/joyent/node/pull/25268
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Julien Gilli <jgilli@fastmail.fm>
v0.12.3-release
Mike Tunnicliffe 10 years ago
committed by Julien Gilli
parent
commit
80cdae855f
  1. 5
      deps/v8/src/base/platform/platform-posix.cc
  2. 4
      deps/v8/src/base/platform/platform-win32.cc
  3. 4
      deps/v8/src/base/platform/platform.h
  4. 26
      deps/v8/src/cpu-profiler.cc
  5. 3
      deps/v8/src/optimizing-compiler-thread.cc
  6. 2
      deps/v8/src/runtime.cc
  7. 2
      deps/v8/src/sampler.cc
  8. 10
      deps/v8/test/cctest/test-api.cc
  9. 2
      deps/v8/test/cctest/test-cpu-profiler.cc
  10. 4
      deps/v8/test/cctest/test-log.cc

5
deps/v8/src/base/platform/platform-posix.cc

@ -268,9 +268,8 @@ size_t OS::AllocateAlignment() {
} }
void OS::Sleep(int milliseconds) { void OS::Sleep(TimeDelta interval) {
useconds_t ms = static_cast<useconds_t>(milliseconds); usleep(static_cast<useconds_t>(interval.InMicroseconds()));
usleep(1000 * ms);
} }

4
deps/v8/src/base/platform/platform-win32.cc

@ -821,8 +821,8 @@ void OS::Guard(void* address, const size_t size) {
} }
void OS::Sleep(int milliseconds) { void OS::Sleep(TimeDelta interval) {
::Sleep(milliseconds); ::Sleep(static_cast<DWORD>(interval.InMilliseconds()));
} }

4
deps/v8/src/base/platform/platform.h

@ -227,8 +227,8 @@ class OS {
// Get the Alignment guaranteed by Allocate(). // Get the Alignment guaranteed by Allocate().
static size_t AllocateAlignment(); static size_t AllocateAlignment();
// Sleep for a number of milliseconds. // Sleep for a specified time interval.
static void Sleep(const int milliseconds); static void Sleep(TimeDelta interval);
// Abort the current process. // Abort the current process.
static void Abort(); static void Abort();

26
deps/v8/src/cpu-profiler.cc

@ -108,16 +108,32 @@ ProfilerEventsProcessor::SampleProcessingResult
void ProfilerEventsProcessor::Run() { void ProfilerEventsProcessor::Run() {
while (running_) { while (running_) {
base::ElapsedTimer timer; base::TimeTicks nextSampleTime =
timer.Start(); base::TimeTicks::HighResolutionNow() + period_;
// Keep processing existing events until we need to do next sample. base::TimeTicks now;
SampleProcessingResult result;
// Keep processing existing events until we need to do next sample
// or the ticks buffer is empty.
do { do {
if (FoundSampleForNextCodeEvent == ProcessOneSample()) { result = ProcessOneSample();
if (result == FoundSampleForNextCodeEvent) {
// All ticks of the current last_processed_code_event_id_ are // All ticks of the current last_processed_code_event_id_ are
// processed, proceed to the next code event. // processed, proceed to the next code event.
ProcessCodeEvent(); ProcessCodeEvent();
} }
} while (!timer.HasExpired(period_)); now = base::TimeTicks::HighResolutionNow();
} while (result != NoSamplesInQueue && now < nextSampleTime);
if (nextSampleTime > now) {
#if V8_OS_WIN
// Do not use Sleep on Windows as it is very imprecise.
// Could be up to 16ms jitter, which is unacceptable for the purpose.
while (base::TimeTicks::HighResolutionNow() < nextSampleTime) {
}
#else
base::OS::Sleep(nextSampleTime - now);
#endif
}
// Schedule next sample. sampler_ is NULL in tests. // Schedule next sample. sampler_ is NULL in tests.
if (sampler_) sampler_->DoSample(); if (sampler_) sampler_->DoSample();

3
deps/v8/src/optimizing-compiler-thread.cc

@ -48,7 +48,8 @@ void OptimizingCompilerThread::Run() {
TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_); TimerEventScope<TimerEventRecompileConcurrent> timer(isolate_);
if (FLAG_concurrent_recompilation_delay != 0) { if (FLAG_concurrent_recompilation_delay != 0) {
base::OS::Sleep(FLAG_concurrent_recompilation_delay); base::OS::Sleep(base::TimeDelta::FromMilliseconds(
FLAG_concurrent_recompilation_delay));
} }
switch (static_cast<StopFlag>(base::Acquire_Load(&stop_thread_))) { switch (static_cast<StopFlag>(base::Acquire_Load(&stop_thread_))) {

2
deps/v8/src/runtime.cc

@ -8641,7 +8641,7 @@ RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
sync_with_compiler_thread) { sync_with_compiler_thread) {
while (function->IsInOptimizationQueue()) { while (function->IsInOptimizationQueue()) {
isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
base::OS::Sleep(50); base::OS::Sleep(base::TimeDelta::FromMilliseconds(50));
} }
} }
if (FLAG_always_opt) { if (FLAG_always_opt) {

2
deps/v8/src/sampler.cc

@ -550,7 +550,7 @@ class SamplerThread : public base::Thread {
sampler->DoSample(); sampler->DoSample();
} }
} }
base::OS::Sleep(interval_); base::OS::Sleep(base::TimeDelta::FromMilliseconds(interval_));
} }
} }

10
deps/v8/test/cctest/test-api.cc

@ -15166,10 +15166,12 @@ class RegExpInterruptionThread : public v8::base::Thread {
for (regexp_interruption_data.loop_count = 0; for (regexp_interruption_data.loop_count = 0;
regexp_interruption_data.loop_count < 7; regexp_interruption_data.loop_count < 7;
regexp_interruption_data.loop_count++) { regexp_interruption_data.loop_count++) {
v8::base::OS::Sleep(50); // Wait a bit before requesting GC. // Wait a bit before requesting GC.
v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC(); reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
} }
v8::base::OS::Sleep(50); // Wait a bit before terminating. // Wait a bit before terminating.
v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(50));
v8::V8::TerminateExecution(isolate_); v8::V8::TerminateExecution(isolate_);
} }
@ -21516,7 +21518,7 @@ class ThreadInterruptTest {
struct sigaction action; struct sigaction action;
// Ensure that we'll enter waiting condition // Ensure that we'll enter waiting condition
v8::base::OS::Sleep(100); v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
// Setup signal handler // Setup signal handler
memset(&action, 0, sizeof(action)); memset(&action, 0, sizeof(action));
@ -21527,7 +21529,7 @@ class ThreadInterruptTest {
kill(getpid(), SIGCHLD); kill(getpid(), SIGCHLD);
// Ensure that if wait has returned because of error // Ensure that if wait has returned because of error
v8::base::OS::Sleep(100); v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(100));
// Set value and signal semaphore // Set value and signal semaphore
test_->sem_value_ = 1; test_->sem_value_ = 1;

2
deps/v8/test/cctest/test-cpu-profiler.cc

@ -793,7 +793,7 @@ class TestApiCallbacks {
double start = v8::base::OS::TimeCurrentMillis(); double start = v8::base::OS::TimeCurrentMillis();
double duration = 0; double duration = 0;
while (duration < min_duration_ms_) { while (duration < min_duration_ms_) {
v8::base::OS::Sleep(1); v8::base::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1));
duration = v8::base::OS::TimeCurrentMillis() - start; duration = v8::base::OS::TimeCurrentMillis() - start;
} }
} }

4
deps/v8/test/cctest/test-log.cc

@ -186,7 +186,7 @@ class LoopingJsThread : public LoopingThread {
"var j; for (var i=0; i<10000; ++i) { j = Math.sin(i); }"); "var j; for (var i=0; i<10000; ++i) { j = Math.sin(i); }");
} }
context.Dispose(); context.Dispose();
i::OS::Sleep(1); i::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1));
} }
} }
}; };
@ -206,7 +206,7 @@ class LoopingNonJsThread : public LoopingThread {
SignalRunning(); SignalRunning();
while (IsRunning()) { while (IsRunning()) {
i = std::sin(i); i = std::sin(i);
i::OS::Sleep(1); i::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1));
} }
} }
}; };

Loading…
Cancel
Save