Chromium Code Reviews| 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(n) {\n" | |
| 458 " this.mmm = 0;\n" | |
| 459 " while(n > 1) {\n" | |
|
loislo
2013/04/04 09:53:17
it will run non deterministic time.
yurys
2013/04/04 10:21:05
As long as I don't measure exact time spent in thi
| |
| 460 " n--;\n" | |
| 461 " this.mmm += n * n * n;\n" | |
| 462 " }\n" | |
| 463 " return n;\n" | |
| 464 "}\n" | |
| 465 "function delay() { try { loop(100*1000); } catch(e) { } }\n" | |
| 466 "function bar() { delay(); }\n" | |
| 467 "function baz() { delay(); }\n" | |
| 468 "function foo() {\n" | |
| 469 " try {\n" | |
| 470 " delay();\n" | |
| 471 " bar();\n" | |
| 472 " delay();\n" | |
| 473 " baz();\n" | |
| 474 " } catch (e) { }\n" | |
| 475 "}\n" | |
| 476 "function start() {\n" | |
| 477 " var start = Date.now();\n" | |
| 478 " do {\n" | |
| 479 " foo();\n" | |
| 480 " var duration = Date.now() - start;\n" | |
| 481 " } while (duration < 1000);\n" | |
| 482 " return duration;\n" | |
| 483 "}\n"; | |
| 484 | |
| 485 | |
| 486 // Check that the profile tree for the script above will look like the | |
| 487 // following: | |
| 488 // | |
| 489 // [Top down]: | |
| 490 // 1062 0 (root) [-1] | |
| 491 // 1054 0 start [-1] | |
| 492 // 1054 1 foo [-1] | |
| 493 // 265 0 baz [-1] | |
| 494 // 265 1 delay [-1] | |
| 495 // 264 264 loop [-1] | |
| 496 // 525 3 delay [-1] | |
| 497 // 522 522 loop [-1] | |
| 498 // 263 0 bar [-1] | |
| 499 // 263 1 delay [-1] | |
| 500 // 262 262 loop [-1] | |
| 501 // 2 2 (program) [-1] | |
| 502 // 6 6 (garbage collector) [-1] | |
| 503 TEST(CollectCpuProfile) { | |
| 504 LocalContext env; | |
| 505 v8::HandleScope scope(env->GetIsolate()); | |
| 506 | |
| 507 v8::Script::Compile(v8::String::New(cpu_profiler_test_source))->Run(); | |
| 508 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( | |
| 509 env->Global()->Get(v8::String::New("start"))); | |
| 510 | |
| 511 v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler(); | |
| 512 v8::Local<v8::String> profile_name = v8::String::New("my_profile"); | |
| 513 | |
| 514 cpu_profiler->StartCpuProfiling(profile_name); | |
| 515 function->Call(env->Global(), 0, 0); | |
| 516 const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name); | |
| 517 | |
| 518 CHECK_NE(NULL, profile); | |
| 519 // Dump collected profile to have a better diagnostic in case of failure. | |
| 520 reinterpret_cast<i::CpuProfile*>( | |
| 521 const_cast<v8::CpuProfile*>(profile))->Print(); | |
| 522 | |
| 523 const v8::CpuProfileNode* root = profile->GetTopDownRoot(); | |
| 524 | |
| 525 ScopedVector<v8::Handle<v8::String> > names(3); | |
| 526 names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName); | |
| 527 names[1] = v8::String::New(ProfileGenerator::kProgramEntryName); | |
| 528 names[2] = v8::String::New("start"); | |
| 529 CheckChildrenNames(root, names); | |
| 530 | |
| 531 const v8::CpuProfileNode* startNode = FindChild(root, "start"); | |
| 532 CHECK_EQ(1, startNode->GetChildrenCount()); | |
| 533 | |
| 534 const v8::CpuProfileNode* fooNode = FindChild(startNode, "foo"); | |
| 535 CHECK_EQ(3, fooNode->GetChildrenCount()); | |
| 536 | |
| 537 const char* barBranch[] = { "bar", "delay", "loop" }; | |
| 538 CheckSimpleBranch(fooNode, barBranch, ARRAY_SIZE(barBranch)); | |
| 539 const char* bazBranch[] = { "baz", "delay", "loop" }; | |
| 540 CheckSimpleBranch(fooNode, bazBranch, ARRAY_SIZE(bazBranch)); | |
| 541 const char* delayBranch[] = { "delay", "loop" }; | |
| 542 CheckSimpleBranch(fooNode, delayBranch, ARRAY_SIZE(delayBranch)); | |
| 543 } | |
| OLD | NEW |