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

Side by Side Diff: runtime/vm/profiler.cc

Issue 83093004: Fix shutdown races and move signal blocking into profiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_android.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 <cstdio> 5 #include <cstdio>
6 6
7 #include "platform/utils.h" 7 #include "platform/utils.h"
8 8
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/json_stream.h" 10 #include "vm/json_stream.h"
11 #include "vm/native_symbol.h" 11 #include "vm/native_symbol.h"
12 #include "vm/object.h" 12 #include "vm/object.h"
13 #include "vm/os.h" 13 #include "vm/os.h"
14 #include "vm/profiler.h" 14 #include "vm/profiler.h"
15 #include "vm/signal_handler.h"
15 16
16 namespace dart { 17 namespace dart {
17 18
18 // Notes on locking and signal handling: 19 // Notes on locking and signal handling:
19 // 20 //
20 // The ProfilerManager has a single monitor (monitor_). This monitor guards 21 // The ProfilerManager has a single monitor (monitor_). This monitor guards
21 // access to the schedule list of isolates (isolates_, isolates_size_, etc). 22 // access to the schedule list of isolates (isolates_, isolates_size_, etc).
22 // 23 //
23 // Each isolate has a mutex (profiler_data_mutex_) which protects access 24 // Each isolate has a mutex (profiler_data_mutex_) which protects access
24 // to the isolate's profiler data. 25 // to the isolate's profiler data.
(...skipping 22 matching lines...) Expand all
47 // Signal handling and locking: 48 // Signal handling and locking:
48 // On OSes with pthreads (Android, Linux, and Mac) we use signal delivery 49 // On OSes with pthreads (Android, Linux, and Mac) we use signal delivery
49 // to interrupt the isolate running thread for sampling. After a thread 50 // to interrupt the isolate running thread for sampling. After a thread
50 // is sent the SIGPROF, it is removed from the scheduled isolate list. 51 // is sent the SIGPROF, it is removed from the scheduled isolate list.
51 // Inside the signal handler, after the sample is taken, the isolate is 52 // Inside the signal handler, after the sample is taken, the isolate is
52 // added to the scheduled isolate list again. The side effect of this is 53 // added to the scheduled isolate list again. The side effect of this is
53 // that the signal handler must be able to acquire the isolate profiler data 54 // that the signal handler must be able to acquire the isolate profiler data
54 // mutex and the profile manager monitor. When an isolate running thread 55 // mutex and the profile manager monitor. When an isolate running thread
55 // (potential signal target) calls into an entry point which acquires 56 // (potential signal target) calls into an entry point which acquires
56 // ProfileManager::monitor_ signal delivery must be blocked. An example is 57 // ProfileManager::monitor_ signal delivery must be blocked. An example is
57 // Isolate::SetCurrent which blocks signal delivery while removing the old 58 // ProfileManager::ScheduleIsolate which blocks signal delivery while removing
58 // current isolate from the scheduled list and adding the new current isolate 59 // the scheduling the isolate.
59 // to the scheduled list.
60 // 60 //
61 61
62 // Notes on stack frame walking: 62 // Notes on stack frame walking:
63 // 63 //
64 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames 64 // The sampling profiler will collect up to Sample::kNumStackFrames stack frames
65 // The stack frame walking code uses the frame pointer to traverse the stack. 65 // The stack frame walking code uses the frame pointer to traverse the stack.
66 // If the VM is compiled without frame pointers (which is the default on 66 // If the VM is compiled without frame pointers (which is the default on
67 // recent GCC versions with optimizing enabled) the stack walking code will 67 // recent GCC versions with optimizing enabled) the stack walking code will
68 // fail (sometimes leading to a crash). 68 // fail (sometimes leading to a crash).
69 // 69 //
70 70
71 71
72 DEFINE_FLAG(bool, profile, false, "Enable Sampling Profiler"); 72 DEFINE_FLAG(bool, profile, true, "Enable Sampling Profiler");
73 DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
73 74
74 bool ProfilerManager::initialized_ = false; 75 bool ProfilerManager::initialized_ = false;
75 bool ProfilerManager::shutdown_ = false; 76 bool ProfilerManager::shutdown_ = false;
76 Monitor* ProfilerManager::monitor_ = NULL; 77 Monitor* ProfilerManager::monitor_ = NULL;
77 Isolate** ProfilerManager::isolates_ = NULL; 78 Isolate** ProfilerManager::isolates_ = NULL;
78 intptr_t ProfilerManager::isolates_capacity_ = 0; 79 intptr_t ProfilerManager::isolates_capacity_ = 0;
79 intptr_t ProfilerManager::isolates_size_ = 0; 80 intptr_t ProfilerManager::isolates_size_ = 0;
80 81
81 82
82 void ProfilerManager::InitOnce() { 83 void ProfilerManager::InitOnce() {
83 if (!FLAG_profile) { 84 if (!FLAG_profile) {
84 return; 85 return;
85 } 86 }
86 NativeSymbolResolver::InitOnce(); 87 NativeSymbolResolver::InitOnce();
87 ASSERT(!initialized_); 88 ASSERT(!initialized_);
88 monitor_ = new Monitor(); 89 monitor_ = new Monitor();
89 initialized_ = true; 90 initialized_ = true;
90 ResizeIsolates(16); 91 ResizeIsolates(16);
91 Thread::Start(ThreadMain, 0); 92 Thread::Start(ThreadMain, 0);
92 } 93 }
93 94
94 95
95 void ProfilerManager::Shutdown() { 96 void ProfilerManager::Shutdown() {
96 if (!FLAG_profile) { 97 if (!FLAG_profile) {
97 return; 98 return;
98 } 99 }
99 ASSERT(initialized_); 100 ASSERT(initialized_);
100 ScopedMonitor lock(monitor_); 101 {
101 shutdown_ = true; 102 ScopedSignalBlocker ssb;
102 for (intptr_t i = 0; i < isolates_size_; i++) { 103 {
103 Isolate* isolate = isolates_[i]; 104 ScopedMonitor lock(monitor_);
104 ASSERT(isolate != NULL); 105 shutdown_ = true;
105 FreeIsolateProfilingData(isolate); 106 for (intptr_t i = 0; i < isolates_size_; i++) {
107 Isolate* isolate = isolates_[i];
108 ASSERT(isolate != NULL);
109 FreeIsolateProfilingData(isolate);
110 }
111 isolates_size_ = 0;
112 free(isolates_);
113 isolates_ = NULL;
114 lock.Notify();
115 }
106 } 116 }
107 isolates_size_ = 0;
108 free(isolates_);
109 isolates_ = NULL;
110 lock.Notify();
111 NativeSymbolResolver::ShutdownOnce(); 117 NativeSymbolResolver::ShutdownOnce();
112 } 118 }
113 119
114 120
115 void ProfilerManager::SetupIsolateForProfiling(Isolate* isolate) { 121 void ProfilerManager::SetupIsolateForProfiling(Isolate* isolate) {
116 if (!FLAG_profile) { 122 if (!FLAG_profile) {
117 return; 123 return;
118 } 124 }
119 ASSERT(isolate != NULL); 125 ASSERT(isolate != NULL);
120 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex()); 126 {
121 SampleBuffer* sample_buffer = new SampleBuffer(); 127 ScopedSignalBlocker ssb;
122 IsolateProfilerData* profiler_data = 128 {
123 new IsolateProfilerData(isolate, sample_buffer); 129 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
124 profiler_data->set_sample_interval_micros(1000); 130 SampleBuffer* sample_buffer = new SampleBuffer();
125 isolate->set_profiler_data(profiler_data); 131 IsolateProfilerData* profiler_data =
132 new IsolateProfilerData(isolate, sample_buffer);
133 profiler_data->set_sample_interval_micros(1000);
134 isolate->set_profiler_data(profiler_data);
135 if (FLAG_trace_profiled_isolates) {
136 OS::Print("PROF SETUP %p %s %p\n",
137 isolate,
138 isolate->name(),
139 reinterpret_cast<void*>(Thread::GetCurrentThreadId()));
140 }
141 }
142 }
126 } 143 }
127 144
128 145
129 void ProfilerManager::FreeIsolateProfilingData(Isolate* isolate) { 146 void ProfilerManager::FreeIsolateProfilingData(Isolate* isolate) {
130 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex()); 147 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
131 IsolateProfilerData* profiler_data = isolate->profiler_data(); 148 IsolateProfilerData* profiler_data = isolate->profiler_data();
132 if (profiler_data == NULL) { 149 if (profiler_data == NULL) {
133 // Already freed. 150 // Already freed.
134 return; 151 return;
135 } 152 }
136 isolate->set_profiler_data(NULL); 153 isolate->set_profiler_data(NULL);
137 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); 154 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
138 ASSERT(sample_buffer != NULL); 155 ASSERT(sample_buffer != NULL);
139 delete sample_buffer; 156 delete sample_buffer;
140 delete profiler_data; 157 delete profiler_data;
158 if (FLAG_trace_profiled_isolates) {
159 OS::Print("PROF SHUTDOWN %p %s %p\n", isolate,
160 isolate->name(), reinterpret_cast<void*>(Thread::GetCurrentThreadId()));
161 }
141 } 162 }
142 163
143 164
144 void ProfilerManager::ShutdownIsolateForProfiling(Isolate* isolate) { 165 void ProfilerManager::ShutdownIsolateForProfiling(Isolate* isolate) {
145 ASSERT(isolate != NULL); 166 ASSERT(isolate != NULL);
146 if (!FLAG_profile) { 167 if (!FLAG_profile) {
147 return; 168 return;
148 } 169 }
149 FreeIsolateProfilingData(isolate); 170 {
171 ScopedSignalBlocker ssb;
172 FreeIsolateProfilingData(isolate);
173 }
150 } 174 }
151 175
152 176
153 void ProfilerManager::ScheduleIsolate(Isolate* isolate) { 177 void ProfilerManager::ScheduleIsolate(Isolate* isolate, bool inside_signal) {
154 if (!FLAG_profile) { 178 if (!FLAG_profile) {
155 return; 179 return;
156 } 180 }
157 ASSERT(initialized_); 181 ASSERT(initialized_);
158 ASSERT(isolate != NULL); 182 ASSERT(isolate != NULL);
159 ScopedMonitor lock(monitor_); 183 {
160 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex()); 184 ScopedSignalBlocker ssb;
161 IsolateProfilerData* profiler_data = isolate->profiler_data(); 185 {
162 if (profiler_data == NULL) { 186 ScopedMonitor lock(monitor_);
163 return; 187 {
188 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
189 IsolateProfilerData* profiler_data = isolate->profiler_data();
190 if (profiler_data == NULL) {
191 return;
192 }
193 profiler_data->Scheduled(OS::GetCurrentTimeMicros(),
194 Thread::GetCurrentThreadId());
195 AddIsolate(isolate);
196 lock.Notify();
197 }
198 }
164 } 199 }
165 profiler_data->Scheduled(OS::GetCurrentTimeMicros(),
166 Thread::GetCurrentThreadId());
167 AddIsolate(isolate);
168 lock.Notify();
169 } 200 }
170 201
171 202
172 void ProfilerManager::DescheduleIsolate(Isolate* isolate) { 203 void ProfilerManager::DescheduleIsolate(Isolate* isolate) {
173 if (!FLAG_profile) { 204 if (!FLAG_profile) {
174 return; 205 return;
175 } 206 }
176 ASSERT(initialized_); 207 ASSERT(initialized_);
177 ASSERT(isolate != NULL); 208 ASSERT(isolate != NULL);
178 ScopedMonitor lock(monitor_); 209 {
179 intptr_t i = FindIsolate(isolate); 210 ScopedSignalBlocker ssb;
180 if (i < 0) { 211 {
181 // Not scheduled. 212 ScopedMonitor lock(monitor_);
182 return; 213 intptr_t i = FindIsolate(isolate);
214 if (i < 0) {
215 // Not scheduled.
216 return;
217 }
218 {
219 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
220 IsolateProfilerData* profiler_data = isolate->profiler_data();
221 if (profiler_data != NULL) {
222 profiler_data->Descheduled();
223 }
224 }
225 RemoveIsolate(i);
226 lock.Notify();
227 }
183 } 228 }
184 {
185 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
186 IsolateProfilerData* profiler_data = isolate->profiler_data();
187 ASSERT(profiler_data != NULL);
188 profiler_data->Descheduled();
189 }
190 RemoveIsolate(i);
191 lock.Notify();
192 } 229 }
193 230
194 231
195 void PrintToJSONStream(Isolate* isolate, JSONStream* stream) { 232 void PrintToJSONStream(Isolate* isolate, JSONStream* stream) {
196 ASSERT(isolate == Isolate::Current()); 233 ASSERT(isolate == Isolate::Current());
197 { 234 {
198 // We can't get signals here. 235 // We can't get signals here.
199 } 236 }
200 UNIMPLEMENTED(); 237 UNIMPLEMENTED();
201 } 238 }
202 239
203 240
204 void ProfilerManager::ResizeIsolates(intptr_t new_capacity) { 241 void ProfilerManager::ResizeIsolates(intptr_t new_capacity) {
205 ASSERT(new_capacity < kMaxProfiledIsolates); 242 ASSERT(new_capacity < kMaxProfiledIsolates);
206 ASSERT(new_capacity > isolates_capacity_); 243 ASSERT(new_capacity > isolates_capacity_);
207 Isolate* isolate = NULL; 244 Isolate* isolate = NULL;
208 isolates_ = reinterpret_cast<Isolate**>( 245 isolates_ = reinterpret_cast<Isolate**>(
209 realloc(isolates_, sizeof(isolate) * new_capacity)); 246 realloc(isolates_, sizeof(isolate) * new_capacity));
210 isolates_capacity_ = new_capacity; 247 isolates_capacity_ = new_capacity;
211 } 248 }
212 249
213 250
214 void ProfilerManager::AddIsolate(Isolate* isolate) { 251 void ProfilerManager::AddIsolate(Isolate* isolate) {
252 // Must be called with monitor_ locked.
215 if (isolates_ == NULL) { 253 if (isolates_ == NULL) {
216 // We are shutting down. 254 // We are shutting down.
217 return; 255 return;
218 } 256 }
219 // Must be called with monitor_ locked.
220 if (isolates_size_ == isolates_capacity_) { 257 if (isolates_size_ == isolates_capacity_) {
221 ResizeIsolates(isolates_capacity_ == 0 ? 16 : isolates_capacity_ * 2); 258 ResizeIsolates(isolates_capacity_ == 0 ? 16 : isolates_capacity_ * 2);
222 } 259 }
223 isolates_[isolates_size_] = isolate; 260 isolates_[isolates_size_] = isolate;
224 isolates_size_++; 261 isolates_size_++;
225 } 262 }
226 263
227 264
228 intptr_t ProfilerManager::FindIsolate(Isolate* isolate) { 265 intptr_t ProfilerManager::FindIsolate(Isolate* isolate) {
229 // Must be called with monitor_ locked. 266 // Must be called with monitor_ locked.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 } 310 }
274 } 311 }
275 } 312 }
276 return const_cast<char*>(symbol_name); 313 return const_cast<char*>(symbol_name);
277 } 314 }
278 315
279 316
280 void ProfilerManager::WriteTracing(Isolate* isolate, const char* name, 317 void ProfilerManager::WriteTracing(Isolate* isolate, const char* name,
281 Dart_Port port) { 318 Dart_Port port) {
282 ASSERT(isolate == Isolate::Current()); 319 ASSERT(isolate == Isolate::Current());
283 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
284 IsolateProfilerData* profiler_data = isolate->profiler_data();
285 if (profiler_data == NULL) {
286 return;
287 }
288 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
289 ASSERT(sample_buffer != NULL);
290 JSONStream stream(10 * MB);
291 intptr_t tid = reinterpret_cast<intptr_t>(sample_buffer);
292 intptr_t pid = 1;
293 { 320 {
294 JSONArray events(&stream); 321 ScopedSignalBlocker ssb;
Cutch 2013/11/22 23:30:18 NOTE: This function was not changed aside from exp
295 { 322 {
296 JSONObject thread_name(&events); 323 ScopedMutex profiler_data_lock(isolate->profiler_data_mutex());
297 thread_name.AddProperty("name", "thread_name"); 324 IsolateProfilerData* profiler_data = isolate->profiler_data();
298 thread_name.AddProperty("ph", "M"); 325 if (profiler_data == NULL) {
299 thread_name.AddProperty("tid", tid); 326 return;
300 thread_name.AddProperty("pid", pid); 327 }
328 SampleBuffer* sample_buffer = profiler_data->sample_buffer();
329 ASSERT(sample_buffer != NULL);
330 JSONStream stream(10 * MB);
331 intptr_t tid = reinterpret_cast<intptr_t>(sample_buffer);
332 intptr_t pid = 1;
301 { 333 {
302 JSONObject args(&thread_name, "args"); 334 JSONArray events(&stream);
303 args.AddProperty("name", name);
304 }
305 }
306 {
307 JSONObject process_name(&events);
308 process_name.AddProperty("name", "process_name");
309 process_name.AddProperty("ph", "M");
310 process_name.AddProperty("tid", tid);
311 process_name.AddProperty("pid", pid);
312 {
313 JSONObject args(&process_name, "args");
314 args.AddProperty("name", "Dart VM");
315 }
316 }
317 uint64_t last_time = 0;
318 for (Sample* i = sample_buffer->FirstSample();
319 i != sample_buffer->LastSample();
320 i = sample_buffer->NextSample(i)) {
321 if (last_time == 0) {
322 last_time = i->timestamp;
323 }
324 intptr_t delta = i->timestamp - last_time;
325 {
326 double percentage = static_cast<double>(i->cpu_usage) /
327 static_cast<double>(delta) * 100.0;
328 if (percentage != percentage) {
329 percentage = 0.0;
330 }
331 percentage = percentage < 0.0 ? 0.0 : percentage;
332 percentage = percentage > 100.0 ? 100.0 : percentage;
333 { 335 {
334 JSONObject cpu_usage(&events); 336 JSONObject thread_name(&events);
335 cpu_usage.AddProperty("name", "CPU Usage"); 337 thread_name.AddProperty("name", "thread_name");
336 cpu_usage.AddProperty("ph", "C"); 338 thread_name.AddProperty("ph", "M");
337 cpu_usage.AddProperty("tid", tid); 339 thread_name.AddProperty("tid", tid);
338 cpu_usage.AddProperty("pid", pid); 340 thread_name.AddProperty("pid", pid);
339 cpu_usage.AddProperty("ts", static_cast<double>(last_time));
340 { 341 {
341 JSONObject args(&cpu_usage, "args"); 342 JSONObject args(&thread_name, "args");
342 args.AddProperty("CPU", percentage); 343 args.AddProperty("name", name);
343 } 344 }
344 } 345 }
345 { 346 {
346 JSONObject cpu_usage(&events); 347 JSONObject process_name(&events);
347 cpu_usage.AddProperty("name", "CPU Usage"); 348 process_name.AddProperty("name", "process_name");
348 cpu_usage.AddProperty("ph", "C"); 349 process_name.AddProperty("ph", "M");
349 cpu_usage.AddProperty("tid", tid); 350 process_name.AddProperty("tid", tid);
350 cpu_usage.AddProperty("pid", pid); 351 process_name.AddProperty("pid", pid);
351 cpu_usage.AddProperty("ts", static_cast<double>(i->timestamp));
352 { 352 {
353 JSONObject args(&cpu_usage, "args"); 353 JSONObject args(&process_name, "args");
354 args.AddProperty("CPU", percentage); 354 args.AddProperty("name", "Dart VM");
355 } 355 }
356 } 356 }
357 } 357 uint64_t last_time = 0;
358 for (int j = 0; j < Sample::kNumStackFrames; j++) { 358 for (Sample* i = sample_buffer->FirstSample();
359 if (i->pcs[j] == 0) { 359 i != sample_buffer->LastSample();
360 continue; 360 i = sample_buffer->NextSample(i)) {
361 } 361 if (last_time == 0) {
362 bool native_symbol = false; 362 last_time = i->timestamp;
363 char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol); 363 }
364 { 364 intptr_t delta = i->timestamp - last_time;
365 JSONObject begin(&events); 365 {
366 begin.AddProperty("ph", "B"); 366 double percentage = static_cast<double>(i->cpu_usage) /
367 begin.AddProperty("tid", tid); 367 static_cast<double>(delta) * 100.0;
368 begin.AddProperty("pid", pid); 368 if (percentage != percentage) {
369 begin.AddProperty("name", symbol_name); 369 percentage = 0.0;
370 begin.AddProperty("ts", static_cast<double>(last_time)); 370 }
371 } 371 percentage = percentage < 0.0 ? 0.0 : percentage;
372 if (native_symbol) { 372 percentage = percentage > 100.0 ? 100.0 : percentage;
373 NativeSymbolResolver::FreeSymbolName(symbol_name); 373 {
374 JSONObject cpu_usage(&events);
375 cpu_usage.AddProperty("name", "CPU Usage");
376 cpu_usage.AddProperty("ph", "C");
377 cpu_usage.AddProperty("tid", tid);
378 cpu_usage.AddProperty("pid", pid);
379 cpu_usage.AddProperty("ts", static_cast<double>(last_time));
380 {
381 JSONObject args(&cpu_usage, "args");
382 args.AddProperty("CPU", percentage);
383 }
384 }
385 {
386 JSONObject cpu_usage(&events);
387 cpu_usage.AddProperty("name", "CPU Usage");
388 cpu_usage.AddProperty("ph", "C");
389 cpu_usage.AddProperty("tid", tid);
390 cpu_usage.AddProperty("pid", pid);
391 cpu_usage.AddProperty("ts", static_cast<double>(i->timestamp));
392 {
393 JSONObject args(&cpu_usage, "args");
394 args.AddProperty("CPU", percentage);
395 }
396 }
397 }
398 for (int j = 0; j < Sample::kNumStackFrames; j++) {
399 if (i->pcs[j] == 0) {
400 continue;
401 }
402 bool native_symbol = false;
403 char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol);
404 {
405 JSONObject begin(&events);
406 begin.AddProperty("ph", "B");
407 begin.AddProperty("tid", tid);
408 begin.AddProperty("pid", pid);
409 begin.AddProperty("name", symbol_name);
410 begin.AddProperty("ts", static_cast<double>(last_time));
411 }
412 if (native_symbol) {
413 NativeSymbolResolver::FreeSymbolName(symbol_name);
414 }
415 }
416 for (int j = Sample::kNumStackFrames-1; j >= 0; j--) {
417 if (i->pcs[j] == 0) {
418 continue;
419 }
420 bool native_symbol = false;
421 char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol);
422 {
423 JSONObject end(&events);
424 end.AddProperty("ph", "E");
425 end.AddProperty("tid", tid);
426 end.AddProperty("pid", pid);
427 end.AddProperty("name", symbol_name);
428 end.AddProperty("ts", static_cast<double>(i->timestamp));
429 }
430 if (native_symbol) {
431 NativeSymbolResolver::FreeSymbolName(symbol_name);
432 }
433 }
434 last_time = i->timestamp;
374 } 435 }
375 } 436 }
376 for (int j = Sample::kNumStackFrames-1; j >= 0; j--) { 437 char fname[1024];
377 if (i->pcs[j] == 0) { 438 #if defined(TARGET_OS_WINDOWS)
378 continue; 439 snprintf(fname, sizeof(fname)-1, "c:\\tmp\\isolate-%d.prof",
379 } 440 static_cast<int>(port));
380 bool native_symbol = false; 441 #else
381 char* symbol_name = FindSymbolName(i->pcs[j], &native_symbol); 442 snprintf(fname, sizeof(fname)-1, "/tmp/isolate-%d.prof",
382 { 443 static_cast<int>(port));
383 JSONObject end(&events); 444 #endif
384 end.AddProperty("ph", "E"); 445 printf("%s\n", fname);
385 end.AddProperty("tid", tid); 446 FILE* f = fopen(fname, "wb");
386 end.AddProperty("pid", pid); 447 ASSERT(f != NULL);
387 end.AddProperty("name", symbol_name); 448 fputs(stream.ToCString(), f);
388 end.AddProperty("ts", static_cast<double>(i->timestamp)); 449 fclose(f);
389 }
390 if (native_symbol) {
391 NativeSymbolResolver::FreeSymbolName(symbol_name);
392 }
393 }
394 last_time = i->timestamp;
395 } 450 }
396 } 451 }
397 char fname[1024];
398 #if defined(TARGET_OS_WINDOWS)
399 snprintf(fname, sizeof(fname)-1, "c:\\tmp\\isolate-%d.prof",
400 static_cast<int>(port));
401 #else
402 snprintf(fname, sizeof(fname)-1, "/tmp/isolate-%d.prof",
403 static_cast<int>(port));
404 #endif
405 printf("%s\n", fname);
406 FILE* f = fopen(fname, "wb");
407 ASSERT(f != NULL);
408 fputs(stream.ToCString(), f);
409 fclose(f);
410 } 452 }
411 453
412 454
413
414
415
416 IsolateProfilerData::IsolateProfilerData(Isolate* isolate, 455 IsolateProfilerData::IsolateProfilerData(Isolate* isolate,
417 SampleBuffer* sample_buffer) { 456 SampleBuffer* sample_buffer) {
418 isolate_ = isolate; 457 isolate_ = isolate;
419 sample_buffer_ = sample_buffer; 458 sample_buffer_ = sample_buffer;
420 timer_expiration_micros_ = kNoExpirationTime; 459 timer_expiration_micros_ = kNoExpirationTime;
421 last_sampled_micros_ = 0; 460 last_sampled_micros_ = 0;
422 thread_id_ = 0; 461 thread_id_ = 0;
423 } 462 }
424 463
425 464
426 IsolateProfilerData::~IsolateProfilerData() { 465 IsolateProfilerData::~IsolateProfilerData() {
427 } 466 }
428 467
429 468
430 void IsolateProfilerData::SampledAt(int64_t current_time) { 469 void IsolateProfilerData::SampledAt(int64_t current_time) {
431 last_sampled_micros_ = current_time; 470 last_sampled_micros_ = current_time;
432 } 471 }
433 472
434 473
435 void IsolateProfilerData::Scheduled(int64_t current_time, ThreadId thread_id) { 474 void IsolateProfilerData::Scheduled(int64_t current_time, ThreadId thread_id) {
436 timer_expiration_micros_ = current_time + sample_interval_micros_; 475 timer_expiration_micros_ = current_time + sample_interval_micros_;
437 Thread::GetThreadCpuUsage(thread_id, &cpu_usage_);
438 thread_id_ = thread_id; 476 thread_id_ = thread_id;
477 Thread::GetThreadCpuUsage(thread_id_, &cpu_usage_);
439 } 478 }
440 479
441 480
442 void IsolateProfilerData::Descheduled() { 481 void IsolateProfilerData::Descheduled() {
443 // TODO(johnmccutchan): Track when we ran for a fraction of our sample 482 // TODO(johnmccutchan): Track when we ran for a fraction of our sample
444 // interval and incorporate the time difference when scheduling the 483 // interval and incorporate the time difference when scheduling the
445 // isolate again. 484 // isolate again.
446 cpu_usage_ = kDescheduledCpuUsage; 485 cpu_usage_ = kDescheduledCpuUsage;
447 timer_expiration_micros_ = kNoExpirationTime; 486 timer_expiration_micros_ = kNoExpirationTime;
448 thread_id_ = 0;
Cutch 2013/11/22 23:30:18 Only update the thread_id when scheduled.
449 Sample* sample = sample_buffer_->ReserveSample(); 487 Sample* sample = sample_buffer_->ReserveSample();
450 ASSERT(sample != NULL); 488 ASSERT(sample != NULL);
451 sample->timestamp = OS::GetCurrentTimeMicros(); 489 sample->timestamp = OS::GetCurrentTimeMicros();
452 sample->cpu_usage = 0; 490 sample->cpu_usage = 0;
453 sample->vm_tags = Sample::kIdle; 491 sample->vm_tags = Sample::kIdle;
454 } 492 }
455 493
456 494
457 const char* Sample::kLookupSymbol = "Symbol Not Looked Up"; 495 const char* Sample::kLookupSymbol = "Symbol Not Looked Up";
458 const char* Sample::kNoSymbol = "No Symbol Found"; 496 const char* Sample::kNoSymbol = "No Symbol Found";
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 return false; 621 return false;
584 } 622 }
585 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp); 623 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp);
586 cursor += sizeof(fp); 624 cursor += sizeof(fp);
587 bool r = cursor >= lower_bound_ && cursor < stack_upper_; 625 bool r = cursor >= lower_bound_ && cursor < stack_upper_;
588 return r; 626 return r;
589 } 627 }
590 628
591 629
592 } // namespace dart 630 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/profiler.h ('k') | runtime/vm/profiler_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698