OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 // | 27 // |
28 // Tests of profiles generator and utilities. | 28 // Tests of profiles generator and utilities. |
29 | 29 |
30 #include "v8.h" | 30 #include "v8.h" |
31 #include "cpu-profiler-inl.h" | 31 #include "cpu-profiler-inl.h" |
32 #include "cctest.h" | 32 #include "cctest.h" |
| 33 #include "utils.h" |
33 #include "../include/v8-profiler.h" | 34 #include "../include/v8-profiler.h" |
34 | 35 |
35 using i::CodeEntry; | 36 using i::CodeEntry; |
36 using i::CpuProfile; | 37 using i::CpuProfile; |
37 using i::CpuProfiler; | 38 using i::CpuProfiler; |
38 using i::CpuProfilesCollection; | 39 using i::CpuProfilesCollection; |
39 using i::ProfileGenerator; | 40 using i::ProfileGenerator; |
40 using i::ProfileNode; | 41 using i::ProfileNode; |
41 using i::ProfilerEventsProcessor; | 42 using i::ProfilerEventsProcessor; |
| 43 using i::ScopedVector; |
42 using i::TokenEnumerator; | 44 using i::TokenEnumerator; |
| 45 using i::Vector; |
43 | 46 |
44 | 47 |
45 TEST(StartStop) { | 48 TEST(StartStop) { |
46 CpuProfilesCollection profiles; | 49 CpuProfilesCollection profiles; |
47 ProfileGenerator generator(&profiles); | 50 ProfileGenerator generator(&profiles); |
48 ProfilerEventsProcessor processor(&generator); | 51 ProfilerEventsProcessor processor(&generator); |
49 processor.Start(); | 52 processor.Start(); |
50 processor.Stop(); | 53 processor.Stop(); |
51 processor.Join(); | 54 processor.Join(); |
52 } | 55 } |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); | 395 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); |
393 CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); | 396 CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); |
394 const_cast<v8::CpuProfile*>(p2)->Delete(); | 397 const_cast<v8::CpuProfile*>(p2)->Delete(); |
395 CHECK_EQ(1, cpu_profiler->GetProfileCount()); | 398 CHECK_EQ(1, cpu_profiler->GetProfileCount()); |
396 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); | 399 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid2)); |
397 CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); | 400 CHECK_EQ(p3, cpu_profiler->FindCpuProfile(uid3)); |
398 const_cast<v8::CpuProfile*>(p3)->Delete(); | 401 const_cast<v8::CpuProfile*>(p3)->Delete(); |
399 CHECK_EQ(0, cpu_profiler->GetProfileCount()); | 402 CHECK_EQ(0, cpu_profiler->GetProfileCount()); |
400 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid3)); | 403 CHECK_EQ(NULL, cpu_profiler->FindCpuProfile(uid3)); |
401 } | 404 } |
| 405 |
| 406 |
| 407 static bool ContainsString(v8::Handle<v8::String> string, |
| 408 const Vector<v8::Handle<v8::String> >& vector) { |
| 409 for (int i = 0; i < vector.length(); i++) { |
| 410 if (string->Equals(vector[i])) |
| 411 return true; |
| 412 } |
| 413 return false; |
| 414 } |
| 415 |
| 416 |
| 417 static void CheckChildrenNames(const v8::CpuProfileNode* node, |
| 418 const Vector<v8::Handle<v8::String> >& names) { |
| 419 int count = node->GetChildrenCount(); |
| 420 for (int i = 0; i < count; i++) { |
| 421 v8::Handle<v8::String> name = node->GetChild(i)->GetFunctionName(); |
| 422 CHECK(ContainsString(name, names)); |
| 423 // Check that there are no duplicates. |
| 424 for (int j = 0; j < count; j++) { |
| 425 if (j == i) continue; |
| 426 CHECK_NE(name, node->GetChild(j)->GetFunctionName()); |
| 427 } |
| 428 } |
| 429 } |
| 430 |
| 431 |
| 432 static const v8::CpuProfileNode* FindChild(const v8::CpuProfileNode* node, |
| 433 const char* name) { |
| 434 int count = node->GetChildrenCount(); |
| 435 v8::Handle<v8::String> nameHandle = v8::String::New(name); |
| 436 for (int i = 0; i < count; i++) { |
| 437 const v8::CpuProfileNode* child = node->GetChild(i); |
| 438 if (nameHandle->Equals(child->GetFunctionName())) return child; |
| 439 } |
| 440 CHECK(false); |
| 441 return NULL; |
| 442 } |
| 443 |
| 444 |
| 445 static void CheckSimpleBranch(const v8::CpuProfileNode* node, |
| 446 const char* names[], int length) { |
| 447 for (int i = 0; i < length; i++) { |
| 448 const char* name = names[i]; |
| 449 node = FindChild(node, name); |
| 450 CHECK(node); |
| 451 int expectedChildrenCount = (i == length - 1) ? 0 : 1; |
| 452 CHECK_EQ(expectedChildrenCount, node->GetChildrenCount()); |
| 453 } |
| 454 } |
| 455 |
| 456 |
| 457 static const char* cpu_profiler_test_source = "function loop(timeout) {\n" |
| 458 " this.mmm = 0;\n" |
| 459 " var start = Date.now();\n" |
| 460 " while (Date.now() - start < timeout) {\n" |
| 461 " var n = 100*1000;\n" |
| 462 " while(n > 1) {\n" |
| 463 " n--;\n" |
| 464 " this.mmm += n * n * n;\n" |
| 465 " }\n" |
| 466 " }\n" |
| 467 "}\n" |
| 468 "function delay() { try { loop(10); } catch(e) { } }\n" |
| 469 "function bar() { delay(); }\n" |
| 470 "function baz() { delay(); }\n" |
| 471 "function foo() {\n" |
| 472 " try {\n" |
| 473 " delay();\n" |
| 474 " bar();\n" |
| 475 " delay();\n" |
| 476 " baz();\n" |
| 477 " } catch (e) { }\n" |
| 478 "}\n" |
| 479 "function start() {\n" |
| 480 " var start = Date.now();\n" |
| 481 " do {\n" |
| 482 " foo();\n" |
| 483 " var duration = Date.now() - start;\n" |
| 484 " } while (duration < 200);\n" |
| 485 " return duration;\n" |
| 486 "}\n"; |
| 487 |
| 488 |
| 489 // Check that the profile tree for the script above will look like the |
| 490 // following: |
| 491 // |
| 492 // [Top down]: |
| 493 // 1062 0 (root) [-1] |
| 494 // 1054 0 start [-1] |
| 495 // 1054 1 foo [-1] |
| 496 // 265 0 baz [-1] |
| 497 // 265 1 delay [-1] |
| 498 // 264 264 loop [-1] |
| 499 // 525 3 delay [-1] |
| 500 // 522 522 loop [-1] |
| 501 // 263 0 bar [-1] |
| 502 // 263 1 delay [-1] |
| 503 // 262 262 loop [-1] |
| 504 // 2 2 (program) [-1] |
| 505 // 6 6 (garbage collector) [-1] |
| 506 TEST(CollectCpuProfile) { |
| 507 LocalContext env; |
| 508 v8::HandleScope scope(env->GetIsolate()); |
| 509 |
| 510 v8::Script::Compile(v8::String::New(cpu_profiler_test_source))->Run(); |
| 511 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( |
| 512 env->Global()->Get(v8::String::New("start"))); |
| 513 |
| 514 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); |
| 515 v8::Local<v8::String> profile_name = v8::String::New("my_profile"); |
| 516 |
| 517 cpu_profiler->StartCpuProfiling(profile_name); |
| 518 function->Call(env->Global(), 0, 0); |
| 519 const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); |
| 520 |
| 521 CHECK_NE(NULL, profile); |
| 522 // Dump collected profile to have a better diagnostic in case of failure. |
| 523 reinterpret_cast<i::CpuProfile*>( |
| 524 const_cast<v8::CpuProfile*>(profile))->Print(); |
| 525 |
| 526 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); |
| 527 |
| 528 ScopedVector<v8::Handle<v8::String> > names(3); |
| 529 names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName); |
| 530 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); |
| 531 names[2] = v8::String::New("start"); |
| 532 CheckChildrenNames(root, names); |
| 533 |
| 534 const v8::CpuProfileNode* startNode = FindChild(root, "start"); |
| 535 CHECK_EQ(1, startNode->GetChildrenCount()); |
| 536 |
| 537 const v8::CpuProfileNode* fooNode = FindChild(startNode, "foo"); |
| 538 CHECK_EQ(3, fooNode->GetChildrenCount()); |
| 539 |
| 540 const char* barBranch[] = { "bar", "delay", "loop" }; |
| 541 CheckSimpleBranch(fooNode, barBranch, ARRAY_SIZE(barBranch)); |
| 542 const char* bazBranch[] = { "baz", "delay", "loop" }; |
| 543 CheckSimpleBranch(fooNode, bazBranch, ARRAY_SIZE(bazBranch)); |
| 544 const char* delayBranch[] = { "delay", "loop" }; |
| 545 CheckSimpleBranch(fooNode, delayBranch, ARRAY_SIZE(delayBranch)); |
| 546 } |
OLD | NEW |