OLD | NEW |
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 "platform/assert.h" | 5 #include "platform/assert.h" |
6 | 6 |
7 #include "vm/dart_api_impl.h" | 7 #include "vm/dart_api_impl.h" |
8 #include "vm/dart_api_state.h" | 8 #include "vm/dart_api_state.h" |
9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
10 #include "vm/profiler.h" | 10 #include "vm/profiler.h" |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 Profile profile(isolate); | 309 Profile profile(isolate); |
310 AllocationFilter filter(isolate->main_port(), class_a.id(), | 310 AllocationFilter filter(isolate->main_port(), class_a.id(), |
311 Dart_TimelineGetMicros(), 16000); | 311 Dart_TimelineGetMicros(), 16000); |
312 profile.Build(thread, &filter, Profile::kNoTags); | 312 profile.Build(thread, &filter, Profile::kNoTags); |
313 // We should have no allocation samples because none occured within | 313 // We should have no allocation samples because none occured within |
314 // the specified time range. | 314 // the specified time range. |
315 EXPECT_EQ(0, profile.sample_count()); | 315 EXPECT_EQ(0, profile.sample_count()); |
316 } | 316 } |
317 } | 317 } |
318 | 318 |
319 #if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && \ | |
320 !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA) | |
321 | |
322 DART_NOINLINE static void NativeAllocationSampleHelper(char** result) { | |
323 ASSERT(result != NULL); | |
324 *result = static_cast<char*>(malloc(sizeof(char) * 1024)); | |
325 } | |
326 | |
327 | |
328 ISOLATE_UNIT_TEST_CASE(Profiler_NativeAllocation) { | |
329 bool enable_malloc_hooks_saved = FLAG_enable_malloc_hooks; | |
330 FLAG_enable_malloc_hooks = true; | |
331 | |
332 MallocHooks::InitOnce(); | |
333 MallocHooks::ResetStats(); | |
334 bool stack_trace_collection_enabled = | |
335 MallocHooks::stack_trace_collection_enabled(); | |
336 MallocHooks::set_stack_trace_collection_enabled(true); | |
337 | |
338 char* result = NULL; | |
339 const int64_t before_allocations_micros = Dart_TimelineGetMicros(); | |
340 NativeAllocationSampleHelper(&result); | |
341 | |
342 // Disable stack allocation stack trace collection to avoid muddying up | |
343 // results. | |
344 MallocHooks::set_stack_trace_collection_enabled(false); | |
345 const int64_t after_allocations_micros = Dart_TimelineGetMicros(); | |
346 const int64_t allocation_extent_micros = | |
347 after_allocations_micros - before_allocations_micros; | |
348 | |
349 // Walk the trie and do a sanity check of the allocation values associated | |
350 // with each node. | |
351 { | |
352 Thread* thread = Thread::Current(); | |
353 Isolate* isolate = thread->isolate(); | |
354 StackZone zone(thread); | |
355 HANDLESCOPE(thread); | |
356 Profile profile(isolate); | |
357 | |
358 // Filter for the class in the time range. | |
359 NativeAllocationSampleFilter filter(before_allocations_micros, | |
360 allocation_extent_micros); | |
361 profile.Build(thread, &filter, Profile::kNoTags); | |
362 // We should have 1 allocation sample. | |
363 EXPECT_EQ(1, profile.sample_count()); | |
364 ProfileTrieWalker walker(&profile); | |
365 | |
366 // Exclusive code: NativeAllocationSampleHelper -> main. | |
367 walker.Reset(Profile::kExclusiveCode); | |
368 // Move down from the root. | |
369 EXPECT(walker.Down()); | |
370 EXPECT_SUBSTRING("[Native]", walker.CurrentName()); | |
371 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
372 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 1024); | |
373 EXPECT(walker.Down()); | |
374 EXPECT_STREQ("dart::Dart_TestProfiler_NativeAllocation()", | |
375 walker.CurrentName()); | |
376 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
377 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
378 EXPECT(walker.Down()); | |
379 EXPECT_STREQ("dart::TestCase::Run()", walker.CurrentName()); | |
380 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
381 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
382 EXPECT(walker.Down()); | |
383 EXPECT_STREQ("dart::TestCaseBase::RunTest()", walker.CurrentName()); | |
384 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
385 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
386 EXPECT(walker.Down()); | |
387 EXPECT_STREQ("dart::TestCaseBase::RunAll()", walker.CurrentName()); | |
388 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
389 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
390 EXPECT(walker.Down()); | |
391 EXPECT_STREQ("main", walker.CurrentName()); | |
392 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
393 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
394 EXPECT(!walker.Down()); | |
395 | |
396 // Inclusive code: main -> NativeAllocationSampleHelper. | |
397 walker.Reset(Profile::kInclusiveCode); | |
398 // Move down from the root. | |
399 EXPECT(walker.Down()); | |
400 EXPECT_STREQ("main", walker.CurrentName()); | |
401 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
402 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
403 EXPECT(walker.Down()); | |
404 EXPECT_STREQ("dart::TestCaseBase::RunAll()", walker.CurrentName()); | |
405 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
406 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
407 EXPECT(walker.Down()); | |
408 EXPECT_STREQ("dart::TestCaseBase::RunTest()", walker.CurrentName()); | |
409 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
410 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
411 EXPECT(walker.Down()); | |
412 EXPECT_STREQ("dart::TestCase::Run()", walker.CurrentName()); | |
413 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
414 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
415 EXPECT(walker.Down()); | |
416 EXPECT_STREQ("dart::Dart_TestProfiler_NativeAllocation()", | |
417 walker.CurrentName()); | |
418 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
419 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
420 EXPECT(walker.Down()); | |
421 EXPECT_SUBSTRING("[Native]", walker.CurrentName()); | |
422 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
423 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 1024); | |
424 EXPECT(!walker.Down()); | |
425 | |
426 // Exclusive function: NativeAllocationSampleHelper -> main. | |
427 walker.Reset(Profile::kExclusiveFunction); | |
428 // Move down from the root. | |
429 EXPECT(walker.Down()); | |
430 EXPECT_SUBSTRING("[Native]", walker.CurrentName()); | |
431 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
432 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 1024); | |
433 EXPECT(walker.Down()); | |
434 EXPECT_STREQ("dart::Dart_TestProfiler_NativeAllocation()", | |
435 walker.CurrentName()); | |
436 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
437 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
438 EXPECT(walker.Down()); | |
439 EXPECT_STREQ("dart::TestCase::Run()", walker.CurrentName()); | |
440 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
441 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
442 EXPECT(walker.Down()); | |
443 EXPECT_STREQ("dart::TestCaseBase::RunTest()", walker.CurrentName()); | |
444 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
445 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
446 EXPECT(walker.Down()); | |
447 EXPECT_STREQ("dart::TestCaseBase::RunAll()", walker.CurrentName()); | |
448 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
449 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
450 EXPECT(walker.Down()); | |
451 EXPECT_STREQ("main", walker.CurrentName()); | |
452 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
453 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
454 EXPECT(!walker.Down()); | |
455 | |
456 // Inclusive function: main -> NativeAllocationSampleHelper. | |
457 walker.Reset(Profile::kInclusiveFunction); | |
458 // Move down from the root. | |
459 EXPECT(walker.Down()); | |
460 EXPECT_STREQ("main", walker.CurrentName()); | |
461 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
462 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
463 EXPECT(walker.Down()); | |
464 EXPECT_STREQ("dart::TestCaseBase::RunAll()", walker.CurrentName()); | |
465 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
466 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
467 EXPECT(walker.Down()); | |
468 EXPECT_STREQ("dart::TestCaseBase::RunTest()", walker.CurrentName()); | |
469 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
470 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
471 EXPECT(walker.Down()); | |
472 EXPECT_STREQ("dart::TestCase::Run()", walker.CurrentName()); | |
473 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
474 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
475 EXPECT(walker.Down()); | |
476 EXPECT_STREQ("dart::Dart_TestProfiler_NativeAllocation()", | |
477 walker.CurrentName()); | |
478 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
479 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 0); | |
480 EXPECT(walker.Down()); | |
481 EXPECT_SUBSTRING("[Native]", walker.CurrentName()); | |
482 EXPECT_EQ(walker.CurrentInclusiveAllocations(), 1024); | |
483 EXPECT_EQ(walker.CurrentExclusiveAllocations(), 1024); | |
484 EXPECT(!walker.Down()); | |
485 } | |
486 | |
487 MallocHooks::set_stack_trace_collection_enabled(true); | |
488 free(result); | |
489 MallocHooks::set_stack_trace_collection_enabled(false); | |
490 | |
491 // Check to see that the native allocation sample associated with the memory | |
492 // freed above is marked as free and is no longer reported. | |
493 { | |
494 Thread* thread = Thread::Current(); | |
495 Isolate* isolate = thread->isolate(); | |
496 StackZone zone(thread); | |
497 HANDLESCOPE(thread); | |
498 Profile profile(isolate); | |
499 | |
500 // Filter for the class in the time range. | |
501 NativeAllocationSampleFilter filter(before_allocations_micros, | |
502 allocation_extent_micros); | |
503 profile.Build(thread, &filter, Profile::kNoTags); | |
504 // We should have 0 allocation samples since we freed the memory. | |
505 EXPECT_EQ(0, profile.sample_count()); | |
506 } | |
507 | |
508 // Query with a time filter where no allocations occurred. | |
509 { | |
510 Thread* thread = Thread::Current(); | |
511 Isolate* isolate = thread->isolate(); | |
512 StackZone zone(thread); | |
513 HANDLESCOPE(thread); | |
514 Profile profile(isolate); | |
515 NativeAllocationSampleFilter filter(Dart_TimelineGetMicros(), 16000); | |
516 profile.Build(thread, &filter, Profile::kNoTags); | |
517 // We should have no allocation samples because none occured within | |
518 // the specified time range. | |
519 EXPECT_EQ(0, profile.sample_count()); | |
520 } | |
521 | |
522 MallocHooks::set_stack_trace_collection_enabled( | |
523 stack_trace_collection_enabled); | |
524 MallocHooks::TearDown(); | |
525 FLAG_enable_malloc_hooks = enable_malloc_hooks_saved; | |
526 } | |
527 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && | |
528 // !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA) | |
529 | |
530 | 319 |
531 TEST_CASE(Profiler_ToggleRecordAllocation) { | 320 TEST_CASE(Profiler_ToggleRecordAllocation) { |
532 DisableNativeProfileScope dnps; | 321 DisableNativeProfileScope dnps; |
533 const char* kScript = | 322 const char* kScript = |
534 "class A {\n" | 323 "class A {\n" |
535 " var a;\n" | 324 " var a;\n" |
536 " var b;\n" | 325 " var b;\n" |
537 "}\n" | 326 "}\n" |
538 "class B {\n" | 327 "class B {\n" |
539 " static boo() {\n" | 328 " static boo() {\n" |
(...skipping 2265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2805 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString()); | 2594 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString()); |
2806 // Verify exclusive ticks in main. | 2595 // Verify exclusive ticks in main. |
2807 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString()); | 2596 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString()); |
2808 // Verify inclusive ticks in main. | 2597 // Verify inclusive ticks in main. |
2809 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); | 2598 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); |
2810 } | 2599 } |
2811 | 2600 |
2812 #endif // !PRODUCT | 2601 #endif // !PRODUCT |
2813 | 2602 |
2814 } // namespace dart | 2603 } // namespace dart |
OLD | NEW |