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 |
319 | 530 |
320 TEST_CASE(Profiler_ToggleRecordAllocation) { | 531 TEST_CASE(Profiler_ToggleRecordAllocation) { |
321 DisableNativeProfileScope dnps; | 532 DisableNativeProfileScope dnps; |
322 const char* kScript = | 533 const char* kScript = |
323 "class A {\n" | 534 "class A {\n" |
324 " var a;\n" | 535 " var a;\n" |
325 " var b;\n" | 536 " var b;\n" |
326 "}\n" | 537 "}\n" |
327 "class B {\n" | 538 "class B {\n" |
328 " static boo() {\n" | 539 " static boo() {\n" |
(...skipping 2265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2594 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString()); | 2805 EXPECT_SUBSTRING("\"positions\":[\"TempMove\",39]", js.ToCString()); |
2595 // Verify exclusive ticks in main. | 2806 // Verify exclusive ticks in main. |
2596 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString()); | 2807 EXPECT_SUBSTRING("\"exclusiveTicks\":[1,0]", js.ToCString()); |
2597 // Verify inclusive ticks in main. | 2808 // Verify inclusive ticks in main. |
2598 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); | 2809 EXPECT_SUBSTRING("\"inclusiveTicks\":[1,2]", js.ToCString()); |
2599 } | 2810 } |
2600 | 2811 |
2601 #endif // !PRODUCT | 2812 #endif // !PRODUCT |
2602 | 2813 |
2603 } // namespace dart | 2814 } // namespace dart |
OLD | NEW |