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 |