Index: src/profile-generator.h |
diff --git a/src/profile-generator.h b/src/profile-generator.h |
index b02ba8575ef94e5e3e2c20cceb35fede20a50c13..bd5b0cd24f64fba67eaf68a5c2ed805810072391 100644 |
--- a/src/profile-generator.h |
+++ b/src/profile-generator.h |
@@ -70,9 +70,11 @@ class CodeEntry { |
}; |
+class ProfileTree; |
+ |
class ProfileNode { |
public: |
- INLINE(explicit ProfileNode(CodeEntry* entry)); |
+ INLINE(ProfileNode(ProfileTree* tree, CodeEntry* entry)); |
ProfileNode* FindChild(CodeEntry* entry); |
ProfileNode* FindOrAddChild(CodeEntry* entry); |
@@ -80,9 +82,11 @@ class ProfileNode { |
INLINE(void IncreaseTotalTicks(unsigned amount)) { total_ticks_ += amount; } |
INLINE(CodeEntry* entry() const) { return entry_; } |
- INLINE(unsigned total_ticks() const) { return total_ticks_; } |
INLINE(unsigned self_ticks() const) { return self_ticks_; } |
+ INLINE(unsigned total_ticks() const) { return total_ticks_; } |
INLINE(const List<ProfileNode*>* children() const) { return &children_list_; } |
+ double GetSelfMillis() const; |
+ double GetTotalMillis() const; |
void Print(int indent); |
@@ -95,6 +99,7 @@ class ProfileNode { |
return static_cast<int32_t>(reinterpret_cast<intptr_t>(entry)); |
} |
+ ProfileTree* tree_; |
CodeEntry* entry_; |
unsigned total_ticks_; |
unsigned self_ticks_; |
@@ -115,7 +120,11 @@ class ProfileTree { |
void AddPathFromStart(const Vector<CodeEntry*>& path); |
void CalculateTotalTicks(); |
+ double TicksToMillis(unsigned ticks) const { |
+ return ticks * ms_to_ticks_scale_; |
+ } |
ProfileNode* root() const { return root_; } |
+ void SetTickRatePerMs(double ticks_per_ms); |
void ShortPrint(); |
void Print() { |
@@ -124,10 +133,11 @@ class ProfileTree { |
private: |
template <typename Callback> |
- void TraverseBreadthFirstPostOrder(Callback* callback); |
+ void TraverseDepthFirstPostOrder(Callback* callback); |
CodeEntry root_entry_; |
ProfileNode* root_; |
+ double ms_to_ticks_scale_; |
DISALLOW_COPY_AND_ASSIGN(ProfileTree); |
}; |
@@ -141,12 +151,15 @@ class CpuProfile { |
// Add pc -> ... -> main() call path to the profile. |
void AddPath(const Vector<CodeEntry*>& path); |
void CalculateTotalTicks(); |
+ void SetActualSamplingRate(double actual_sampling_rate); |
INLINE(const char* title() const) { return title_; } |
INLINE(unsigned uid() const) { return uid_; } |
INLINE(const ProfileTree* top_down() const) { return &top_down_; } |
INLINE(const ProfileTree* bottom_up() const) { return &bottom_up_; } |
+ void UpdateTicksScale(); |
+ |
void ShortPrint(); |
void Print(); |
@@ -208,8 +221,8 @@ class CpuProfilesCollection { |
bool StartProfiling(const char* title, unsigned uid); |
bool StartProfiling(String* title, unsigned uid); |
- CpuProfile* StopProfiling(const char* title); |
- CpuProfile* StopProfiling(String* title); |
+ CpuProfile* StopProfiling(const char* title, double actual_sampling_rate); |
+ CpuProfile* StopProfiling(String* title, double actual_sampling_rate); |
INLINE(List<CpuProfile*>* profiles()) { return &profiles_; } |
CpuProfile* GetProfile(unsigned uid); |
inline bool is_last_profile(); |
@@ -256,6 +269,42 @@ class CpuProfilesCollection { |
}; |
+class SampleRateCalculator { |
+ public: |
+ SampleRateCalculator() |
+ : result_(Logger::kSamplingIntervalMs * kResultScale), |
+ ticks_per_ms_(Logger::kSamplingIntervalMs), |
+ measurements_count_(0), |
+ wall_time_query_countdown_(1) { |
+ } |
+ |
+ double ticks_per_ms() { |
+ return result_ / static_cast<double>(kResultScale); |
+ } |
+ void Tick(); |
+ void UpdateMeasurements(double current_time); |
+ |
+ // Instead of querying current wall time each tick, |
+ // we use this constant to control query intervals. |
+ static const unsigned kWallTimeQueryIntervalMs = 100; |
+ |
+ private: |
+ // As the result needs to be accessed from a different thread, we |
+ // use type that guarantees atomic writes to memory. There should |
+ // be <= 1000 ticks per second, thus storing a value of a 10 ** 5 |
+ // order should provide enough precision while keeping away from a |
+ // potential overflow. |
+ static const int kResultScale = 100000; |
+ |
+ AtomicWord result_; |
+ // All other fields are accessed only from the sampler thread. |
+ double ticks_per_ms_; |
+ unsigned measurements_count_; |
+ unsigned wall_time_query_countdown_; |
+ double last_wall_time_; |
+}; |
+ |
+ |
class ProfileGenerator { |
public: |
explicit ProfileGenerator(CpuProfilesCollection* profiles); |
@@ -287,6 +336,11 @@ class ProfileGenerator { |
INLINE(CodeMap* code_map()) { return &code_map_; } |
+ INLINE(void Tick()) { sample_rate_calc_.Tick(); } |
+ INLINE(double actual_sampling_rate()) { |
+ return sample_rate_calc_.ticks_per_ms(); |
+ } |
+ |
static const char* kAnonymousFunctionName; |
static const char* kProgramEntryName; |
static const char* kGarbageCollectorEntryName; |
@@ -298,6 +352,7 @@ class ProfileGenerator { |
CodeMap code_map_; |
CodeEntry* program_entry_; |
CodeEntry* gc_entry_; |
+ SampleRateCalculator sample_rate_calc_; |
DISALLOW_COPY_AND_ASSIGN(ProfileGenerator); |
}; |