[turboprop] Delay optimizing functions that get hot slower

Functions that get hot quickly are more likely to stay hot and stable,
so optimize these functions earlier than the function that become
hot slower. To measure how "soon" the function gets hot this cl
introduces a global tick that is incremented whenever a function
registers a tick. We use the difference in the global tick between the
current tick and the last tick on that function to measure how soon
the function is becoming hot. We use the last tick to account for
functions that aren't used so much at the start but become hot
in a later phase. Currently we use this heuristic only for Turboprop
tierups. It is possible to extend this to extend this to Turbofan in
future.

Bug: v8:9684
Change-Id: I8ef265c03520274c68d56a9d35429531a3ba3d1d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2627850
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72281}
This commit is contained in:
Mythri A 2021-01-25 09:36:51 +00:00 committed by Commit Bot
parent 27485b3535
commit 502419a803
5 changed files with 46 additions and 1 deletions

View File

@ -48,6 +48,19 @@ static const int kMaxBytecodeSizeForEarlyOpt = 90;
// FLAG_ticks_scale_factor_for_top_tier.
static const int kProfilerTicksForTurboPropOSR = 4 * 10;
// These are used to decide when we tiering up to Turboprop.
// The number of ticks required for tiering up to Turboprop is based on how
// "soon" the function becomes hot. We use kMidTierGlobalTicksScaleFactor to
// scale the difference in global ticks since the last time a function saw a
// tick. The scaled difference is used to to increase the number of ticks
// required for tiering up to Turboprop.
static const int kMidTierGlobalTicksScaleFactor = 100;
// This is used to limit the number of additional ticks that the
// kMidTierGlobalTicksScaleFactor can increase threshold for mid-tier tier
// tierup.
static const int kMaxAdditionalMidTierGlobalTicks = 10;
#define OPTIMIZATION_REASON_LIST(V) \
V(DoNotOptimize, "do not optimize") \
V(HotAndStable, "hot and stable") \
@ -121,7 +134,7 @@ void TraceRecompile(JSFunction function, OptimizationReason reason,
} // namespace
RuntimeProfiler::RuntimeProfiler(Isolate* isolate)
: isolate_(isolate), any_ic_changed_(false) {}
: isolate_(isolate), any_ic_changed_(false), current_global_ticks_(0) {}
void RuntimeProfiler::Optimize(JSFunction function, OptimizationReason reason,
CodeKind code_kind) {
@ -192,6 +205,9 @@ void RuntimeProfiler::MaybeOptimizeFrame(JSFunction function,
if (reason != OptimizationReason::kDoNotOptimize) {
Optimize(function, reason, code_kind);
}
function.feedback_vector()
.set_global_ticks_at_last_runtime_profiler_interrupt(
current_global_ticks_);
}
bool RuntimeProfiler::MaybeOSR(JSFunction function, InterpretedFrame* frame) {
@ -266,6 +282,17 @@ OptimizationReason RuntimeProfiler::ShouldOptimize(JSFunction function,
int ticks_for_optimization =
kProfilerTicksBeforeOptimization +
(bytecode.length() / kBytecodeSizeAllowancePerTick);
if (FLAG_turboprop && !active_tier_is_turboprop) {
DCHECK_EQ(function.NextTier(), CodeKind::TURBOPROP);
int global_ticks_diff =
(current_global_ticks_ -
function.feedback_vector()
.global_ticks_at_last_runtime_profiler_interrupt());
ticks_for_optimization =
ticks_for_optimization +
std::min(global_ticks_diff / kMidTierGlobalTicksScaleFactor,
kMaxAdditionalMidTierGlobalTicks);
}
ticks_for_optimization *= scale_factor;
if (ticks >= ticks_for_optimization) {
return OptimizationReason::kHotAndStable;
@ -294,6 +321,10 @@ RuntimeProfiler::MarkCandidatesForOptimizationScope::
: handle_scope_(profiler->isolate_), profiler_(profiler) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
"V8.MarkCandidatesForOptimization");
if (profiler_->current_global_ticks_ <
FeedbackVector::GlobalTicksAtLastRuntimeProfilerInterruptBits::kMax - 1) {
profiler_->current_global_ticks_ += 1;
}
}
RuntimeProfiler::MarkCandidatesForOptimizationScope::

View File

@ -65,6 +65,7 @@ class RuntimeProfiler {
Isolate* isolate_;
bool any_ic_changed_;
unsigned int current_global_ticks_;
};
} // namespace internal

View File

@ -126,6 +126,16 @@ OptimizationMarker FeedbackVector::optimization_marker() const {
return OptimizationMarkerBits::decode(flags());
}
int FeedbackVector::global_ticks_at_last_runtime_profiler_interrupt() const {
return GlobalTicksAtLastRuntimeProfilerInterruptBits::decode(flags());
}
void FeedbackVector::set_global_ticks_at_last_runtime_profiler_interrupt(
int ticks) {
set_flags(
GlobalTicksAtLastRuntimeProfilerInterruptBits::update(flags(), ticks));
}
OptimizationTier FeedbackVector::optimization_tier() const {
OptimizationTier tier = OptimizationTierBits::decode(flags());
// It is possible that the optimization tier bits aren't updated when the code

View File

@ -217,6 +217,8 @@ class FeedbackVector
inline bool has_optimization_marker() const;
inline OptimizationMarker optimization_marker() const;
inline OptimizationTier optimization_tier() const;
inline int global_ticks_at_last_runtime_profiler_interrupt() const;
inline void set_global_ticks_at_last_runtime_profiler_interrupt(int ticks);
void ClearOptimizedCode();
void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo shared,
const char* reason);

View File

@ -8,6 +8,7 @@ type OptimizationTier extends uint16 constexpr 'OptimizationTier';
bitfield struct FeedbackVectorFlags extends uint32 {
optimization_marker: OptimizationMarker: 3 bit;
optimization_tier: OptimizationTier: 2 bit;
global_ticks_at_last_runtime_profiler_interrupt: uint32: 24 bit;
}
@generateBodyDescriptor