Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(720)

Side by Side Diff: src/heap-profiler.cc

Issue 267077: Add initial semi-working producers profile. (Closed)
Patch Set: Comments addressed Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap-profiler.h ('k') | src/log.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 10 matching lines...) Expand all
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "heap-profiler.h" 30 #include "heap-profiler.h"
31 #include "frames-inl.h"
32 #include "global-handles.h"
31 #include "string-stream.h" 33 #include "string-stream.h"
32 34
33 namespace v8 { 35 namespace v8 {
34 namespace internal { 36 namespace internal {
35 37
36 38
37 #ifdef ENABLE_LOGGING_AND_PROFILING 39 #ifdef ENABLE_LOGGING_AND_PROFILING
38 namespace { 40 namespace {
39 41
40 // Clusterizer is a set of helper functions for converting 42 // Clusterizer is a set of helper functions for converting
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 void ConstructorHeapProfile::CollectStats(HeapObject* obj) { 322 void ConstructorHeapProfile::CollectStats(HeapObject* obj) {
321 Clusterizer::InsertIntoTree(&js_objects_info_tree_, obj, false); 323 Clusterizer::InsertIntoTree(&js_objects_info_tree_, obj, false);
322 } 324 }
323 325
324 326
325 void ConstructorHeapProfile::PrintStats() { 327 void ConstructorHeapProfile::PrintStats() {
326 js_objects_info_tree_.ForEach(this); 328 js_objects_info_tree_.ForEach(this);
327 } 329 }
328 330
329 331
332 static const char* GetConstructorName(const char* name) {
333 return name[0] != '\0' ? name : "(anonymous)";
334 }
335
336
330 void JSObjectsCluster::Print(StringStream* accumulator) const { 337 void JSObjectsCluster::Print(StringStream* accumulator) const {
331 ASSERT(!is_null()); 338 ASSERT(!is_null());
332 if (constructor_ == FromSpecialCase(ROOTS)) { 339 if (constructor_ == FromSpecialCase(ROOTS)) {
333 accumulator->Add("(roots)"); 340 accumulator->Add("(roots)");
334 } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) { 341 } else if (constructor_ == FromSpecialCase(GLOBAL_PROPERTY)) {
335 accumulator->Add("(global property)"); 342 accumulator->Add("(global property)");
336 } else if (constructor_ == FromSpecialCase(SELF)) { 343 } else if (constructor_ == FromSpecialCase(SELF)) {
337 accumulator->Add("(self)"); 344 accumulator->Add("(self)");
338 } else { 345 } else {
339 SmartPointer<char> s_name( 346 SmartPointer<char> s_name(
340 constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); 347 constructor_->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
341 accumulator->Add("%s", (*s_name)[0] != '\0' ? *s_name : "(anonymous)"); 348 accumulator->Add("%s", GetConstructorName(*s_name));
342 if (instance_ != NULL) { 349 if (instance_ != NULL) {
343 accumulator->Add(":%p", static_cast<void*>(instance_)); 350 accumulator->Add(":%p", static_cast<void*>(instance_));
344 } 351 }
345 } 352 }
346 } 353 }
347 354
348 355
349 void JSObjectsCluster::DebugPrint(StringStream* accumulator) const { 356 void JSObjectsCluster::DebugPrint(StringStream* accumulator) const {
350 if (!is_null()) { 357 if (!is_null()) {
351 Print(accumulator); 358 Print(accumulator);
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 // HeapProfiler class implementation. 574 // HeapProfiler class implementation.
568 // 575 //
569 void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) { 576 void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) {
570 InstanceType type = obj->map()->instance_type(); 577 InstanceType type = obj->map()->instance_type();
571 ASSERT(0 <= type && type <= LAST_TYPE); 578 ASSERT(0 <= type && type <= LAST_TYPE);
572 info[type].increment_number(1); 579 info[type].increment_number(1);
573 info[type].increment_bytes(obj->Size()); 580 info[type].increment_bytes(obj->Size());
574 } 581 }
575 582
576 583
584 static void StackWeakReferenceCallback(Persistent<Value> object,
585 void* trace) {
586 DeleteArray(static_cast<Address*>(trace));
587 object.Dispose();
588 }
589
590
591 static void PrintProducerStackTrace(Object* obj, void* trace) {
592 if (!obj->IsJSObject()) return;
593 String* constructor = JSObject::cast(obj)->constructor_name();
594 SmartPointer<char> s_name(
595 constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
596 LOG(HeapSampleJSProducerEvent(GetConstructorName(*s_name),
597 reinterpret_cast<Address*>(trace)));
598 }
599
600
577 void HeapProfiler::WriteSample() { 601 void HeapProfiler::WriteSample() {
578 LOG(HeapSampleBeginEvent("Heap", "allocated")); 602 LOG(HeapSampleBeginEvent("Heap", "allocated"));
579 LOG(HeapSampleStats( 603 LOG(HeapSampleStats(
580 "Heap", "allocated", Heap::Capacity(), Heap::SizeOfObjects())); 604 "Heap", "allocated", Heap::Capacity(), Heap::SizeOfObjects()));
581 605
582 HistogramInfo info[LAST_TYPE+1]; 606 HistogramInfo info[LAST_TYPE+1];
583 #define DEF_TYPE_NAME(name) info[name].set_name(#name); 607 #define DEF_TYPE_NAME(name) info[name].set_name(#name);
584 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) 608 INSTANCE_TYPE_LIST(DEF_TYPE_NAME)
585 #undef DEF_TYPE_NAME 609 #undef DEF_TYPE_NAME
586 610
(...skipping 22 matching lines...) Expand all
609 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) { 633 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) {
610 if (info[i].bytes() > 0) { 634 if (info[i].bytes() > 0) {
611 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(), 635 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(),
612 info[i].bytes())); 636 info[i].bytes()));
613 } 637 }
614 } 638 }
615 639
616 js_cons_profile.PrintStats(); 640 js_cons_profile.PrintStats();
617 js_retainer_profile.PrintStats(); 641 js_retainer_profile.PrintStats();
618 642
643 GlobalHandles::IterateWeakRoots(PrintProducerStackTrace,
644 StackWeakReferenceCallback);
645
619 LOG(HeapSampleEndEvent("Heap", "allocated")); 646 LOG(HeapSampleEndEvent("Heap", "allocated"));
620 } 647 }
621 648
622 649
650 bool ProducerHeapProfile::can_log_ = false;
651
652 void ProducerHeapProfile::Setup() {
653 can_log_ = true;
654 }
655
656 void ProducerHeapProfile::RecordJSObjectAllocation(Object* obj) {
657 if (!can_log_ || !FLAG_log_producers) return;
658 int framesCount = 0;
659 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
660 ++framesCount;
661 }
662 if (framesCount == 0) return;
663 ++framesCount; // Reserve place for the terminator item.
664 Vector<Address> stack(NewArray<Address>(framesCount), framesCount);
665 int i = 0;
666 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
667 stack[i++] = it.frame()->pc();
668 }
669 stack[i] = NULL;
670 Handle<Object> handle = GlobalHandles::Create(obj);
671 GlobalHandles::MakeWeak(handle.location(),
672 static_cast<void*>(stack.start()),
673 StackWeakReferenceCallback);
674 }
675
676
623 #endif // ENABLE_LOGGING_AND_PROFILING 677 #endif // ENABLE_LOGGING_AND_PROFILING
624 678
625 679
626 } } // namespace v8::internal 680 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap-profiler.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698