v8/src/logging/counters-scopes.h
Camillo Bruni 6956482764 [counters] Improve v8.execute histogram timer
- Mark uncommon timer-paths as V8_NOINLINE
- Add explicit LongTaskNestedTimedHistogramScope class
- Use explicit LongTaskRecordMode enum
- Mark a few more isolate methods as const
- Add more timer scopes:
  - Accessors::ArrayLengthSetter
  - v8::NewContext

Bug: v8:12498, chromium:1275056
Change-Id: I7896ee341c3c3a1fd5acf8f3f59347ff01dda9c0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3338258
Reviewed-by: Marja Hölttä <marja@chromium.org>
Auto-Submit: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78372}
2021-12-14 16:14:05 +00:00

244 lines
6.9 KiB
C++

// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_LOGGING_COUNTERS_SCOPES_H_
#define V8_LOGGING_COUNTERS_SCOPES_H_
#include "src/execution/isolate.h"
#include "src/logging/counters.h"
#include "src/logging/log.h"
namespace v8 {
namespace internal {
class BaseTimedHistogramScope {
protected:
explicit BaseTimedHistogramScope(TimedHistogram* histogram)
: histogram_(histogram) {}
void StartInternal() {
DCHECK(histogram_->ToggleRunningState(true));
timer_.Start();
}
void StopInternal() {
DCHECK(histogram_->ToggleRunningState(false));
histogram_->AddTimedSample(timer_.Elapsed());
timer_.Stop();
}
V8_INLINE void Start() {
if (histogram_->Enabled()) StartInternal();
}
V8_INLINE void Stop() {
if (histogram_->Enabled()) StopInternal();
}
V8_INLINE void LogStart(Isolate* isolate) {
Logger::CallEventLogger(isolate, histogram_->name(),
v8::LogEventStatus::kStart, true);
}
V8_INLINE void LogEnd(Isolate* isolate) {
Logger::CallEventLogger(isolate, histogram_->name(),
v8::LogEventStatus::kEnd, true);
}
base::ElapsedTimer timer_;
TimedHistogram* histogram_;
};
// Helper class for scoping a TimedHistogram.
class V8_NODISCARD TimedHistogramScope : public BaseTimedHistogramScope {
public:
explicit TimedHistogramScope(TimedHistogram* histogram,
Isolate* isolate = nullptr)
: BaseTimedHistogramScope(histogram), isolate_(isolate) {
Start();
if (isolate_) LogStart(isolate_);
}
~TimedHistogramScope() {
Stop();
if (isolate_) LogEnd(isolate_);
}
private:
Isolate* const isolate_;
DISALLOW_IMPLICIT_CONSTRUCTORS(TimedHistogramScope);
};
enum class OptionalTimedHistogramScopeMode { TAKE_TIME, DONT_TAKE_TIME };
// Helper class for scoping a TimedHistogram.
// It will not take time for mode = DONT_TAKE_TIME.
class V8_NODISCARD OptionalTimedHistogramScope
: public BaseTimedHistogramScope {
public:
OptionalTimedHistogramScope(TimedHistogram* histogram, Isolate* isolate,
OptionalTimedHistogramScopeMode mode)
: BaseTimedHistogramScope(histogram), isolate_(isolate), mode_(mode) {
if (mode != OptionalTimedHistogramScopeMode::TAKE_TIME) return;
Start();
LogStart(isolate_);
}
~OptionalTimedHistogramScope() {
if (mode_ != OptionalTimedHistogramScopeMode::TAKE_TIME) return;
Stop();
LogEnd(isolate_);
}
private:
Isolate* const isolate_;
const OptionalTimedHistogramScopeMode mode_;
DISALLOW_IMPLICIT_CONSTRUCTORS(OptionalTimedHistogramScope);
};
// Helper class for scoping a TimedHistogram, where the histogram is selected at
// stop time rather than start time.
class V8_NODISCARD LazyTimedHistogramScope : public BaseTimedHistogramScope {
public:
LazyTimedHistogramScope() : BaseTimedHistogramScope(nullptr) {
timer_.Start();
}
~LazyTimedHistogramScope() {
// We should set the histogram before this scope exits.
Stop();
}
void set_histogram(TimedHistogram* histogram) {
DCHECK_IMPLIES(histogram->Enabled(), histogram->ToggleRunningState(true));
histogram_ = histogram;
}
};
// Helper class for scoping a NestedHistogramTimer.
class V8_NODISCARD NestedTimedHistogramScope : public BaseTimedHistogramScope {
public:
enum class LongTaskRecordMode { kSkip, kRecord };
explicit NestedTimedHistogramScope(
NestedTimedHistogram* histogram,
LongTaskRecordMode long_task_record_mode = LongTaskRecordMode::kSkip)
: BaseTimedHistogramScope(histogram),
long_task_record_mode_(long_task_record_mode) {
Start();
}
~NestedTimedHistogramScope() { Stop(); }
private:
friend NestedTimedHistogram;
friend PauseNestedTimedHistogramScope;
V8_INLINE void Start() {
if (histogram_->Enabled()) StartInteral();
LogStart(isolate());
}
V8_NOINLINE void StartInteral() {
previous_scope_ = timed_histogram()->Enter(this);
base::TimeTicks now = base::TimeTicks::HighResolutionNow();
if (previous_scope_) previous_scope_->Pause(now);
timer_.Start(now);
}
void Pause(base::TimeTicks now) {
DCHECK(histogram_->Enabled());
timer_.Pause(now);
}
V8_INLINE void Stop() {
if (histogram_->Enabled()) StopInternal();
LogEnd(isolate());
}
V8_NOINLINE void StopInternal() {
timed_histogram()->Leave(previous_scope_);
base::TimeTicks now = base::TimeTicks::HighResolutionNow();
base::TimeDelta elapsed = timer_.Elapsed(now);
histogram_->AddTimedSample(elapsed);
if (long_task_record_mode_ == LongTaskRecordMode::kRecord) {
RecordLongTaskTime(elapsed);
}
#ifdef DEBUG
// StopInternal() is called in the destructor and don't access timer_
// after that.
timer_.Stop();
#endif
if (previous_scope_) previous_scope_->Resume(now);
}
void Resume(base::TimeTicks now) {
DCHECK(histogram_->Enabled());
timer_.Resume(now);
}
void RecordLongTaskTime(base::TimeDelta elapsed) const {
if (histogram_ == timed_histogram()->counters()->execute()) {
isolate()->GetCurrentLongTaskStats()->v8_execute_us +=
elapsed.InMicroseconds();
}
}
Isolate* isolate() const { return timed_histogram()->counters()->isolate(); }
NestedTimedHistogram* timed_histogram() const {
return static_cast<NestedTimedHistogram*>(histogram_);
}
NestedTimedHistogramScope* previous_scope_;
LongTaskRecordMode long_task_record_mode_;
};
class V8_NODISCARD LongTaskNestedTimedHistogramScope
: public NestedTimedHistogramScope {
public:
explicit LongTaskNestedTimedHistogramScope(NestedTimedHistogram* histogram)
: NestedTimedHistogramScope(histogram, LongTaskRecordMode::kRecord) {}
};
// Temporarily pause a NestedTimedHistogram when for instance leaving V8 for
// external callbacks.
class V8_NODISCARD PauseNestedTimedHistogramScope {
public:
explicit PauseNestedTimedHistogramScope(NestedTimedHistogram* histogram)
: histogram_(histogram) {
if (isEnabled()) Pause();
}
~PauseNestedTimedHistogramScope() {
if (isEnabled()) Resume();
}
private:
bool isEnabled() const { return previous_scope_ && histogram_->Enabled(); }
V8_NOINLINE void Pause() {
previous_scope_ = histogram_->Enter(nullptr);
// For performance reasons we don't annotate all internal callbacks with
// NestedTimerScopes which might lead to double pausing and minor
// inaccuracies.
// TODO(v8:12498): Add DCHECK_NOT_NULL(previous_scope_)
if (previous_scope_) {
previous_scope_->Pause(base::TimeTicks::HighResolutionNow());
}
}
V8_NOINLINE void Resume() {
histogram_->Leave(previous_scope_);
previous_scope_->Resume(base::TimeTicks::HighResolutionNow());
}
NestedTimedHistogram* histogram_;
NestedTimedHistogramScope* previous_scope_;
};
} // namespace internal
} // namespace v8
#endif // V8_LOGGING_COUNTERS_SCOPES_H_