OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/compiler_stats.h" | 5 #include "vm/compiler_stats.h" |
6 | 6 |
7 #include "vm/flags.h" | 7 #include "vm/flags.h" |
8 #include "vm/log.h" | |
8 #include "vm/object_graph.h" | 9 #include "vm/object_graph.h" |
9 #include "vm/timer.h" | 10 #include "vm/timer.h" |
10 | 11 |
11 | 12 |
12 namespace dart { | 13 namespace dart { |
13 | 14 |
14 DEFINE_FLAG(bool, compiler_stats, false, "Compiler stat counters."); | 15 DEFINE_FLAG(bool, compiler_stats, false, "Compiler stat counters."); |
15 | 16 |
16 | 17 |
17 class TokenStreamVisitor : public ObjectGraph::Visitor { | 18 class TokenStreamVisitor : public ObjectVisitor { |
18 public: | 19 public: |
19 explicit TokenStreamVisitor(CompilerStats* compiler_stats) | 20 TokenStreamVisitor(Isolate* isolate, CompilerStats* compiler_stats) |
20 : obj_(Object::Handle()), stats_(compiler_stats) { | 21 : ObjectVisitor(isolate), |
22 obj_(Object::Handle()), | |
23 stats_(compiler_stats) { | |
21 } | 24 } |
22 | 25 |
23 virtual Direction VisitObject(ObjectGraph::StackIterator* it) { | 26 void VisitObject(RawObject* raw_obj) { |
24 RawObject* raw_obj = it->Get(); | |
25 if (raw_obj->IsFreeListElement()) { | 27 if (raw_obj->IsFreeListElement()) { |
26 return kProceed; | 28 return; |
27 } | 29 } |
28 obj_ = raw_obj; | 30 obj_ = raw_obj; |
29 if (obj_.GetClassId() == TokenStream::kClassId) { | 31 if (obj_.GetClassId() == TokenStream::kClassId) { |
30 TokenStream::Iterator tkit(TokenStream::Cast(obj_), | 32 TokenStream::Iterator tkit(TokenStream::Cast(obj_), |
31 0, | 33 0, |
32 TokenStream::Iterator::kNoNewlines); | 34 TokenStream::Iterator::kNoNewlines); |
33 Token::Kind kind = tkit.CurrentTokenKind(); | 35 Token::Kind kind = tkit.CurrentTokenKind(); |
34 while (kind != Token::kEOS) { | 36 while (kind != Token::kEOS) { |
35 ++stats_->num_tokens_total; | 37 ++stats_->num_tokens_total; |
36 if (kind == Token::kIDENT) { | 38 if (kind == Token::kIDENT) { |
37 ++stats_->num_ident_tokens_total; | 39 ++stats_->num_ident_tokens_total; |
38 } else if (Token::NeedsLiteralToken(kind)) { | 40 } else if (Token::NeedsLiteralToken(kind)) { |
39 ++stats_->num_literal_tokens_total; | 41 ++stats_->num_literal_tokens_total; |
40 } | 42 } |
41 tkit.Advance(); | 43 tkit.Advance(); |
42 kind = tkit.CurrentTokenKind(); | 44 kind = tkit.CurrentTokenKind(); |
43 } | 45 } |
44 } | 46 } |
45 return kProceed; | |
46 } | 47 } |
47 | 48 |
48 private: | 49 private: |
49 Object& obj_; | 50 Object& obj_; |
50 CompilerStats* stats_; | 51 CompilerStats* stats_; |
51 }; | 52 }; |
52 | 53 |
53 | 54 |
54 CompilerStats::CompilerStats(Isolate* isolate) | 55 CompilerStats::CompilerStats(Isolate* isolate) |
55 : isolate_(isolate), | 56 : isolate_(isolate), |
56 parser_timer(true, "parser timer"), | 57 parser_timer(true, "parser timer"), |
57 scanner_timer(true, "scanner timer"), | 58 scanner_timer(true, "scanner timer"), |
58 codegen_timer(true, "codegen timer"), | 59 codegen_timer(true, "codegen timer"), |
59 graphbuilder_timer(true, "flow graph builder timer"), | 60 graphbuilder_timer(true, "flow graph builder timer"), |
60 ssa_timer(true, "flow graph SSA timer"), | 61 ssa_timer(true, "flow graph SSA timer"), |
61 graphinliner_timer(true, "flow graph inliner timer"), | 62 graphinliner_timer(true, "flow graph inliner timer"), |
62 graphinliner_parse_timer(true, "inliner parsing timer"), | 63 graphinliner_parse_timer(true, "inliner parsing timer"), |
63 graphinliner_build_timer(true, "inliner building timer"), | 64 graphinliner_build_timer(true, "inliner building timer"), |
64 graphinliner_ssa_timer(true, "inliner SSA timer"), | 65 graphinliner_ssa_timer(true, "inliner SSA timer"), |
65 graphinliner_opt_timer(true, "inliner optimization timer"), | 66 graphinliner_opt_timer(true, "inliner optimization timer"), |
66 graphinliner_subst_timer(true, "inliner substitution timer"), | 67 graphinliner_subst_timer(true, "inliner substitution timer"), |
67 graphoptimizer_timer(true, "flow graph optimizer timer"), | 68 graphoptimizer_timer(true, "flow graph optimizer timer"), |
68 graphcompiler_timer(true, "flow graph compiler timer"), | 69 graphcompiler_timer(true, "flow graph compiler timer"), |
69 codefinalizer_timer(true, "code finalization timer"), | 70 codefinalizer_timer(true, "code finalization timer"), |
70 num_tokens_total(0), | 71 num_tokens_total(0), |
71 num_literal_tokens_total(0), | 72 num_literal_tokens_total(0), |
72 num_ident_tokens_total(0), | 73 num_ident_tokens_total(0), |
73 num_tokens_consumed(0), | 74 num_tokens_consumed(0), |
74 num_token_checks(0), | |
75 num_tokens_lookahead(0), | |
76 num_cached_consts(0), | 75 num_cached_consts(0), |
77 num_const_cache_hits(0), | 76 num_const_cache_hits(0), |
78 num_classes_compiled(0), | 77 num_classes_parsed(0), |
78 num_class_tokens(0), | |
79 num_functions_parsed(0), | |
79 num_functions_compiled(0), | 80 num_functions_compiled(0), |
81 num_functions_optimized(0), | |
82 num_func_tokens_compiled(0), | |
80 num_implicit_final_getters(0), | 83 num_implicit_final_getters(0), |
84 num_method_extractors(0), | |
81 src_length(0), | 85 src_length(0), |
82 total_code_size(0), | 86 total_code_size(0), |
83 total_instr_size(0), | 87 total_instr_size(0), |
84 pc_desc_size(0), | 88 pc_desc_size(0), |
85 vardesc_size(0) { | 89 vardesc_size(0), |
90 text(NULL) { | |
86 } | 91 } |
87 | 92 |
88 | 93 |
89 void CompilerStats::Print() { | 94 static void PrintToStats(const char* format, ...) { |
Ivan Posva
2015/09/04 19:22:59
Please ensure that format and parameters are valid
hausner
2015/09/04 20:45:20
Done.
| |
95 Thread* thread = Thread::Current(); | |
96 Isolate* isolate = thread->isolate(); | |
97 CompilerStats* stats = isolate->compiler_stats(); | |
98 Zone* zone = thread->zone(); | |
99 ASSERT(stats != NULL); | |
100 va_list args; | |
101 va_start(args, format); | |
102 stats->text = zone->VPrint(format, args); | |
103 va_end(args); | |
104 } | |
105 | |
106 | |
107 char* CompilerStats::PrintToZone() { | |
90 if (!FLAG_compiler_stats) { | 108 if (!FLAG_compiler_stats) { |
91 return; | 109 return NULL; |
92 } | 110 } |
93 | 111 |
94 // Traverse the heap and compute number of tokens in all | 112 // Traverse the heap and compute number of tokens in all |
95 // TokenStream objects. | 113 // TokenStream objects. |
96 num_tokens_total = 0; | 114 num_tokens_total = 0; |
97 num_literal_tokens_total = 0; | 115 num_literal_tokens_total = 0; |
98 num_ident_tokens_total = 0; | 116 num_ident_tokens_total = 0; |
99 TokenStreamVisitor visitor(this); | 117 TokenStreamVisitor visitor(isolate_, this); |
100 ObjectGraph graph(isolate_); | 118 isolate_->heap()->IterateObjects(&visitor); |
101 graph.IterateObjects(&visitor); | 119 Dart::vm_isolate()->heap()->IterateObjects(&visitor); |
102 | 120 |
103 OS::Print("==== Compiler Stats for isolate '%s' ====\n", | 121 Log log(PrintToStats); |
122 LogBlock lb(isolate_, &log); | |
123 | |
124 log.Print("==== Compiler Stats for isolate '%s' ====\n", | |
104 isolate_->debugger_name()); | 125 isolate_->debugger_name()); |
105 OS::Print("Number of tokens: %" Pd64 "\n", num_tokens_total); | 126 log.Print("Number of tokens: %" Pd64 "\n", num_tokens_total); |
106 OS::Print(" Literal tokens: %" Pd64 "\n", num_literal_tokens_total); | 127 log.Print(" Literal tokens: %" Pd64 "\n", num_literal_tokens_total); |
107 OS::Print(" Ident tokens: %" Pd64 "\n", num_ident_tokens_total); | 128 log.Print(" Ident tokens: %" Pd64 "\n", num_ident_tokens_total); |
108 OS::Print("Tokens consumed: %" Pd64 " (%.2f times number of tokens)\n", | 129 log.Print("Source length: %" Pd64 " characters\n", src_length); |
109 num_tokens_consumed, | |
110 (1.0 * num_tokens_consumed) / num_tokens_total); | |
111 OS::Print("Tokens checked: %" Pd64 " (%.2f times tokens consumed)\n", | |
112 num_token_checks, (1.0 * num_token_checks) / num_tokens_consumed); | |
113 OS::Print("Token lookahead: %" Pd64 " (%" Pd64 "%% of tokens checked)\n", | |
114 num_tokens_lookahead, | |
115 (100 * num_tokens_lookahead) / num_token_checks); | |
116 OS::Print("Consts cached: %" Pd64 "\n", num_cached_consts); | |
117 OS::Print("Consts cache hits: %" Pd64 "\n", num_const_cache_hits); | |
118 | 130 |
119 OS::Print("Classes parsed: %" Pd64 "\n", num_classes_compiled); | 131 log.Print("==== Parser stats:\n"); |
120 OS::Print("Functions compiled: %" Pd64 "\n", num_functions_compiled); | 132 log.Print("Total tokens consumed: %" Pd64 "\n", num_tokens_consumed); |
121 OS::Print(" Impl getters: %" Pd64 "\n", num_implicit_final_getters); | 133 log.Print("Classes parsed: %" Pd64 "\n", num_classes_parsed); |
134 log.Print(" Tokens consumed: %" Pd64 "\n", num_class_tokens); | |
135 log.Print("Functions parsed: %" Pd64 "\n", num_functions_parsed); | |
136 log.Print(" Tokens consumed: %" Pd64 "\n", num_func_tokens_compiled); | |
137 log.Print("Impl getter funcs: %" Pd64 "\n", num_implicit_final_getters); | |
138 log.Print("Impl method extractors: %" Pd64 "\n", num_method_extractors); | |
139 log.Print("Consts cached: %" Pd64 "\n", num_cached_consts); | |
140 log.Print("Consts cache hits: %" Pd64 "\n", num_const_cache_hits); | |
122 | 141 |
123 OS::Print("Source length: %" Pd64 " characters\n", src_length); | |
124 int64_t scan_usecs = scanner_timer.TotalElapsedTime(); | 142 int64_t scan_usecs = scanner_timer.TotalElapsedTime(); |
125 OS::Print("Scanner time: %" Pd64 " msecs\n", | 143 log.Print("Scanner time: %" Pd64 " msecs\n", scan_usecs / 1000); |
126 scan_usecs / 1000); | |
127 int64_t parse_usecs = parser_timer.TotalElapsedTime(); | 144 int64_t parse_usecs = parser_timer.TotalElapsedTime(); |
128 OS::Print("Parser time: %" Pd64 " msecs\n", | 145 log.Print("Parser time: %" Pd64 " msecs\n", parse_usecs / 1000); |
129 parse_usecs / 1000); | 146 log.Print("Parser speed: %" Pd64 " tokens per msec\n", |
147 1000 * num_tokens_consumed / parse_usecs); | |
130 int64_t codegen_usecs = codegen_timer.TotalElapsedTime(); | 148 int64_t codegen_usecs = codegen_timer.TotalElapsedTime(); |
131 OS::Print("Code gen. time: %" Pd64 " msecs\n", | 149 |
150 log.Print("==== Backend stats:\n"); | |
151 log.Print("Code gen. time: %" Pd64 " msecs\n", | |
132 codegen_usecs / 1000); | 152 codegen_usecs / 1000); |
133 int64_t graphbuilder_usecs = graphbuilder_timer.TotalElapsedTime(); | 153 int64_t graphbuilder_usecs = graphbuilder_timer.TotalElapsedTime(); |
134 OS::Print(" Graph builder: %" Pd64 " msecs\n", graphbuilder_usecs / 1000); | 154 log.Print(" Graph builder: %" Pd64 " msecs\n", |
155 graphbuilder_usecs / 1000); | |
135 int64_t ssa_usecs = ssa_timer.TotalElapsedTime(); | 156 int64_t ssa_usecs = ssa_timer.TotalElapsedTime(); |
136 OS::Print(" Graph SSA: %" Pd64 " msecs\n", ssa_usecs / 1000); | 157 log.Print(" Graph SSA: %" Pd64 " msecs\n", ssa_usecs / 1000); |
137 | 158 |
138 int64_t graphinliner_usecs = graphinliner_timer.TotalElapsedTime(); | 159 int64_t graphinliner_usecs = graphinliner_timer.TotalElapsedTime(); |
139 OS::Print(" Graph inliner: %" Pd64 " msecs\n", graphinliner_usecs / 1000); | 160 log.Print(" Graph inliner: %" Pd64 " msecs\n", |
161 graphinliner_usecs / 1000); | |
140 int64_t graphinliner_parse_usecs = | 162 int64_t graphinliner_parse_usecs = |
141 graphinliner_parse_timer.TotalElapsedTime(); | 163 graphinliner_parse_timer.TotalElapsedTime(); |
142 OS::Print(" Parsing: %" Pd64 " msecs\n", | 164 log.Print(" Parsing: %" Pd64 " msecs\n", |
143 graphinliner_parse_usecs / 1000); | 165 graphinliner_parse_usecs / 1000); |
144 int64_t graphinliner_build_usecs = | 166 int64_t graphinliner_build_usecs = |
145 graphinliner_build_timer.TotalElapsedTime(); | 167 graphinliner_build_timer.TotalElapsedTime(); |
146 OS::Print(" Building: %" Pd64 " msecs\n", | 168 log.Print(" Building: %" Pd64 " msecs\n", |
147 graphinliner_build_usecs / 1000); | 169 graphinliner_build_usecs / 1000); |
148 int64_t graphinliner_ssa_usecs = graphinliner_ssa_timer.TotalElapsedTime(); | 170 int64_t graphinliner_ssa_usecs = graphinliner_ssa_timer.TotalElapsedTime(); |
149 OS::Print(" SSA: %" Pd64 " msecs\n", | 171 log.Print(" SSA: %" Pd64 " msecs\n", |
150 graphinliner_ssa_usecs / 1000); | 172 graphinliner_ssa_usecs / 1000); |
151 int64_t graphinliner_opt_usecs = graphinliner_opt_timer.TotalElapsedTime(); | 173 int64_t graphinliner_opt_usecs = graphinliner_opt_timer.TotalElapsedTime(); |
152 OS::Print(" Optimization: %" Pd64 " msecs\n", | 174 log.Print(" Optimization: %" Pd64 " msecs\n", |
153 graphinliner_opt_usecs / 1000); | 175 graphinliner_opt_usecs / 1000); |
154 int64_t graphinliner_subst_usecs = | 176 int64_t graphinliner_subst_usecs = |
155 graphinliner_subst_timer.TotalElapsedTime(); | 177 graphinliner_subst_timer.TotalElapsedTime(); |
156 OS::Print(" Substitution: %" Pd64 " msecs\n", | 178 log.Print(" Substitution: %" Pd64 " msecs\n", |
157 graphinliner_subst_usecs / 1000); | 179 graphinliner_subst_usecs / 1000); |
158 | |
159 int64_t graphoptimizer_usecs = graphoptimizer_timer.TotalElapsedTime(); | 180 int64_t graphoptimizer_usecs = graphoptimizer_timer.TotalElapsedTime(); |
160 OS::Print(" Graph optimizer: %" Pd64 " msecs\n", | 181 log.Print(" Graph optimizer: %" Pd64 " msecs\n", |
161 (graphoptimizer_usecs - graphinliner_usecs) / 1000); | 182 (graphoptimizer_usecs - graphinliner_usecs) / 1000); |
162 int64_t graphcompiler_usecs = graphcompiler_timer.TotalElapsedTime(); | 183 int64_t graphcompiler_usecs = graphcompiler_timer.TotalElapsedTime(); |
163 OS::Print(" Graph compiler: %" Pd64 " msecs\n", | 184 log.Print(" Graph compiler: %" Pd64 " msecs\n", |
164 graphcompiler_usecs / 1000); | 185 graphcompiler_usecs / 1000); |
165 int64_t codefinalizer_usecs = codefinalizer_timer.TotalElapsedTime(); | 186 int64_t codefinalizer_usecs = codefinalizer_timer.TotalElapsedTime(); |
166 OS::Print(" Code finalizer: %" Pd64 " msecs\n", | 187 log.Print(" Code finalizer: %" Pd64 " msecs\n", |
167 codefinalizer_usecs / 1000); | 188 codefinalizer_usecs / 1000); |
168 OS::Print("Compilation speed: %" Pd64 " tokens per msec\n", | 189 |
169 (1000 * num_tokens_total) / (parse_usecs + codegen_usecs)); | 190 log.Print("==== Compiled code stats:\n"); |
170 OS::Print("Code density: %" Pd64 " tokens per KB\n", | 191 log.Print("Functions parsed: %" Pd64 "\n", num_functions_parsed); |
171 (num_tokens_total * 1024) / total_instr_size); | 192 log.Print("Functions compiled: %" Pd64 "\n", num_functions_compiled); |
172 OS::Print("Instr size: %" Pd64 " KB\n", | 193 log.Print(" optimized: %" Pd64 "\n", num_functions_optimized); |
194 log.Print("Tokens compiled: %" Pd64 "\n", num_func_tokens_compiled); | |
195 log.Print("Compilation speed: %" Pd64 " tokens per msec\n", | |
196 (1000 * num_func_tokens_compiled) / (parse_usecs + codegen_usecs)); | |
197 log.Print("Code density: %" Pd64 " tokens per KB\n", | |
198 (num_func_tokens_compiled * 1024) / total_instr_size); | |
199 log.Print("Code size: %" Pd64 " KB\n", total_code_size / 1024); | |
200 log.Print(" Instr size: %" Pd64 " KB\n", | |
173 total_instr_size / 1024); | 201 total_instr_size / 1024); |
174 OS::Print("Pc Desc size: %" Pd64 " KB\n", pc_desc_size / 1024); | 202 log.Print(" Pc Desc size: %" Pd64 " KB\n", pc_desc_size / 1024); |
175 OS::Print("VarDesc size: %" Pd64 " KB\n", vardesc_size / 1024); | 203 log.Print(" VarDesc size: %" Pd64 " KB\n", vardesc_size / 1024); |
176 | 204 log.Flush(); |
177 OS::Print("Code size: %" Pd64 " KB\n", total_code_size / 1024); | 205 char* stats_text = text; |
206 text = NULL; | |
207 return stats_text; | |
178 } | 208 } |
179 | 209 |
180 } // namespace dart | 210 } // namespace dart |
OLD | NEW |