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

Unified Diff: runtime/vm/profiler_service.h

Issue 1210333002: Make CPU profile models public and refactor model building code (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/vm/profiler_service.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/profiler_service.h
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 19f01b622fee85975a79325066fce04e0ae34411..62612bb1e23232eb54f47c3647c07974dfaad19b 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -8,20 +8,266 @@
#include "vm/allocation.h"
#include "vm/code_observers.h"
#include "vm/globals.h"
+#include "vm/growable_array.h"
+#include "vm/object.h"
#include "vm/tags.h"
#include "vm/thread_interrupter.h"
-// Profile VM Service.
+// CPU Profile model and service protocol bits.
// NOTE: For sampling and stack walking related code, see profiler.h.
namespace dart {
// Forward declarations.
+class Code;
+class Function;
class JSONArray;
class JSONStream;
-class ProfilerCodeRegionTable;
+class ProfileFunctionTable;
+class ProfileCodeTable;
+class RawCode;
+class RawFunction;
+class SampleFilter;
-class ProfilerService : public AllStatic {
+// Profile data related to a |Function|.
+class ProfileFunction : public ZoneAllocated {
+ public:
+ enum Kind {
+ kDartFunction, // Dart function.
+ kNativeFunction, // Synthetic function for Native (C/C++).
+ kTagFunction, // Synthetic function for a VM or User tag.
+ kStubFunction, // Synthetic function for stub code.
+ kUnknownFunction, // A singleton function for unknown objects.
+ };
+
+ ProfileFunction(Kind kind,
+ const char* name,
+ const Function& function,
+ const intptr_t table_index);
+
+ const char* name() const {
+ ASSERT(name_ != NULL);
+ return name_;
+ }
+
+ RawFunction* function() const {
+ return function_.raw();
+ }
+
+ intptr_t table_index() const {
+ return table_index_;
+ }
+
+ Kind kind() const {
+ return kind_;
+ }
+
+ intptr_t exclusive_ticks() const { return exclusive_ticks_; }
+ intptr_t inclusive_ticks() const { return inclusive_ticks_; }
+
+ void IncInclusiveTicks() {
+ inclusive_ticks_++;
+ }
+
+ void Tick(bool exclusive, intptr_t inclusive_serial);
+
+ static const char* KindToCString(Kind kind);
+
+ void PrintToJSONArray(JSONArray* functions);
+
+ private:
+ const Kind kind_;
+ const char* name_;
+ const Function& function_;
+ const intptr_t table_index_;
+ ZoneGrowableArray<intptr_t> profile_codes_;
+
+ intptr_t exclusive_ticks_;
+ intptr_t inclusive_ticks_;
+ intptr_t inclusive_serial_;
+
+ void PrintToJSONObject(JSONObject* func);
+ // A |ProfileCode| that contains this function.
+ void AddProfileCode(intptr_t code_table_index);
+
+ friend class ProfileCode;
+ friend class ProfileBuilder;
+};
+
+
+class ProfileCodeAddress {
+ public:
+ explicit ProfileCodeAddress(uword pc);
+
+ void Tick(bool exclusive);
+
+ uword pc() const { return pc_; }
+ intptr_t exclusive_ticks() const { return exclusive_ticks_; }
+ intptr_t inclusive_ticks() const { return inclusive_ticks_; }
+
+ private:
+ uword pc_;
+ intptr_t exclusive_ticks_;
+ intptr_t inclusive_ticks_;
+};
+
+
+// Profile data related to a |Code|.
+class ProfileCode : public ZoneAllocated {
+ public:
+ enum Kind {
+ kDartCode, // Live Dart code.
+ kCollectedCode, // Dead Dart code.
+ kNativeCode, // Native code.
+ kReusedCode, // Dead Dart code that has been reused by new kDartCode.
+ kTagCode, // A special kind of code representing a tag.
+ };
+
+ ProfileCode(Kind kind,
+ uword start,
+ uword end,
+ int64_t timestamp,
+ const Code& code);
+
+ Kind kind() const { return kind_; }
+
+ uword start() const { return start_; }
+ void set_start(uword start) { start_ = start; }
+
+ uword end() const { return end_; }
+ void set_end(uword end) { end_ = end; }
+
+ void AdjustExtent(uword start, uword end);
+
+ bool Contains(uword pc) const {
+ return (pc >= start_) && (pc < end_);
+ }
+
+ bool Overlaps(const ProfileCode* other) const;
+
+ int64_t compile_timestamp() const { return compile_timestamp_; }
+ void set_compile_timestamp(int64_t timestamp) {
+ compile_timestamp_ = timestamp;
+ }
+
+ intptr_t exclusive_ticks() const { return exclusive_ticks_; }
+ void set_exclusive_ticks(intptr_t exclusive_ticks) {
+ exclusive_ticks_ = exclusive_ticks;
+ }
+ void IncExclusiveTicks() {
+ exclusive_ticks_++;
+ }
+
+ intptr_t inclusive_ticks() const { return inclusive_ticks_; }
+ void set_inclusive_ticks(intptr_t inclusive_ticks) {
+ inclusive_ticks_ = inclusive_ticks;
+ }
+ void IncInclusiveTicks() {
+ inclusive_ticks_++;
+ }
+
+ bool IsOptimizedDart() const;
+ RawCode* code() const {
+ return code_.raw();
+ }
+
+ const char* name() const { return name_; }
+ void SetName(const char* name);
+ void GenerateAndSetSymbolName(const char* prefix);
+
+ static const char* KindToCString(Kind kind);
+
+ void PrintToJSONArray(JSONArray* codes);
+
+ private:
+ void Tick(uword pc, bool exclusive, intptr_t serial);
+ void TickAddress(uword pc, bool exclusive);
+
+ ProfileFunction* SetFunctionAndName(ProfileFunctionTable* table);
+
+ ProfileFunction* function() const {
+ return function_;
+ }
+
+ void PrintNativeCode(JSONObject* profile_code_obj);
+ void PrintCollectedCode(JSONObject* profile_code_obj);
+ void PrintOverwrittenCode(JSONObject* profile_code_obj);
+ void PrintTagCode(JSONObject* profile_code_obj);
+
+ void set_code_table_index(intptr_t index) { code_table_index_ = index; }
+ intptr_t code_table_index() const { return code_table_index_; }
+
+ const Kind kind_;
+ uword start_;
+ uword end_;
+ intptr_t exclusive_ticks_;
+ intptr_t inclusive_ticks_;
+ intptr_t inclusive_serial_;
+
+ const Code& code_;
+ const char* name_;
+ int64_t compile_timestamp_;
+ ProfileFunction* function_;
+ intptr_t code_table_index_;
+ ZoneGrowableArray<ProfileCodeAddress> address_ticks_;
+
+ friend class ProfileBuilder;
+};
+
+
+// Stack traces are organized in a trie. This holds information about one node
+// in the trie. A node in a tree represents a stack frame and a path in the tree
+// represents a stack trace. Each unique stack trace appears in the tree once
+// and each node has a count indicating how many times this has been observed.
+// The index can be used to look up a |ProfileFunction| or |ProfileCode|.
+// A node can have zero or more children. Depending on the kind of trie the
+// children are callers or callees of the current node.
+class ProfileTrieNode : public ZoneAllocated {
+ public:
+ explicit ProfileTrieNode(intptr_t index);
+ virtual ~ProfileTrieNode();
+
+ virtual void PrintToJSONArray(JSONArray* array) const = 0;
+
+ // Index into function or code tables.
+ intptr_t table_index() const { return table_index_; }
+
+ intptr_t count() const { return count_; }
+
+ void Tick() {
+ count_++;
+ }
+
+ intptr_t NumChildren() const {
+ return children_.length();
+ }
+
+ ProfileTrieNode* At(intptr_t i) {
+ return children_.At(i);
+ }
+
+ protected:
+ void SortChildren();
+
+ static int ProfileTrieNodeCompare(ProfileTrieNode* const* a,
+ ProfileTrieNode* const* b) {
+ ASSERT(a != NULL);
+ ASSERT(b != NULL);
+ return (*b)->count() - (*a)->count();
+ }
+
+
+ intptr_t table_index_;
+ intptr_t count_;
+ ZoneGrowableArray<ProfileTrieNode*> children_;
+
+ friend class ProfileBuilder;
+};
+
+
+// The model for a profile. Most of the model is zone allocated, therefore
+// a zone must be created that lives longer than this object.
+class Profile : public ValueObject {
public:
enum TagOrder {
kNoTags,
@@ -31,8 +277,57 @@ class ProfilerService : public AllStatic {
kVMUser
};
+ enum TrieKind {
+ kExclusiveCode,
+ kExclusiveFunction,
+ kInclusiveCode,
+ kInclusiveFunction,
+ kNumTrieKinds,
+ };
+
+ explicit Profile(Isolate* isolate);
+
+ // Build a filtered model using |filter| with the specified |tag_order|.
+ void Build(SampleFilter* filter, TagOrder tag_order);
+
+ // After building:
+ int64_t min_time() const { return min_time_; }
+ int64_t max_time() const { return max_time_; }
+ int64_t GetTimeSpan() const {
+ return max_time() - min_time();
+ }
+ intptr_t sample_count() const { return sample_count_; }
+
+ ProfileFunction* GetFunction(intptr_t index);
+ ProfileCode* GetCode(intptr_t index);
+ ProfileTrieNode* GetTrieRoot(TrieKind trie_kind);
+
+ void PrintJSON(JSONStream* stream);
+
+ private:
+ Isolate* isolate_;
+ ProfileCodeTable* live_code_;
+ ProfileCodeTable* dead_code_;
+ ProfileCodeTable* tag_code_;
+ ProfileFunctionTable* functions_;
+ intptr_t dead_code_index_offset_;
+ intptr_t tag_code_index_offset_;
+
+ ProfileTrieNode* roots_[kNumTrieKinds];
+
+ int64_t min_time_;
+ int64_t max_time_;
+
+ intptr_t sample_count_;
+
+ friend class ProfileBuilder;
+};
+
+
+class ProfilerService : public AllStatic {
+ public:
static void PrintJSON(JSONStream* stream,
- TagOrder tag_order);
+ Profile::TagOrder tag_order);
static void ClearSamples();
};
« no previous file with comments | « no previous file | runtime/vm/profiler_service.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698