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

Side by Side Diff: src/heap.cc

Issue 159504: Introduce first approximation of constructor heap profile for JS objects. (Closed)
Patch Set: Soeren's comments applied Created 11 years, 4 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 | « no previous file | src/jsregexp.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 3393 matching lines...) Expand 10 before | Expand all | Expand 10 after
3404 } 3404 }
3405 3405
3406 3406
3407 void HeapIterator::reset() { 3407 void HeapIterator::reset() {
3408 // Restart the iterator. 3408 // Restart the iterator.
3409 Shutdown(); 3409 Shutdown();
3410 Init(); 3410 Init();
3411 } 3411 }
3412 3412
3413 3413
3414 #ifdef ENABLE_LOGGING_AND_PROFILING
3415 namespace {
3416
3417 // JSConstructorProfile is responsible for gathering and logging
3418 // "constructor profile" of JS object allocated on heap.
3419 // It is run during garbage collection cycle, thus it doesn't need
3420 // to use handles.
3421 class JSConstructorProfile BASE_EMBEDDED {
3422 public:
3423 JSConstructorProfile() : zscope_(DELETE_ON_EXIT) {}
3424 void CollectStats(JSObject* obj);
3425 void PrintStats();
3426 // Used by ZoneSplayTree::ForEach.
3427 void Call(String* name, const NumberAndSizeInfo& number_and_size);
3428 private:
3429 struct TreeConfig {
3430 typedef String* Key;
3431 typedef NumberAndSizeInfo Value;
3432 static const Key kNoKey;
3433 static const Value kNoValue;
3434 // Strings are unique, so it is sufficient to compare their pointers.
3435 static int Compare(const Key& a, const Key& b) {
3436 return a == b ? 0 : (a < b ? -1 : 1);
3437 }
3438 };
3439
3440 typedef ZoneSplayTree<TreeConfig> JSObjectsInfoTree;
3441 static int CalculateJSObjectNetworkSize(JSObject* obj);
3442
3443 ZoneScope zscope_;
3444 JSObjectsInfoTree js_objects_info_tree_;
3445 };
3446
3447 const JSConstructorProfile::TreeConfig::Key
3448 JSConstructorProfile::TreeConfig::kNoKey = NULL;
3449 const JSConstructorProfile::TreeConfig::Value
3450 JSConstructorProfile::TreeConfig::kNoValue;
3451
3452
3453 int JSConstructorProfile::CalculateJSObjectNetworkSize(JSObject* obj) {
3454 int size = obj->Size();
3455 // If 'properties' and 'elements' are non-empty (thus, non-shared),
3456 // take their size into account.
3457 if (FixedArray::cast(obj->properties())->length() != 0) {
3458 size += obj->properties()->Size();
3459 }
3460 if (FixedArray::cast(obj->elements())->length() != 0) {
3461 size += obj->elements()->Size();
3462 }
3463 return size;
3464 }
3465
3466
3467 void JSConstructorProfile::Call(String* name,
3468 const NumberAndSizeInfo& number_and_size) {
3469 SmartPointer<char> s_name;
3470 if (name != NULL) {
3471 s_name = name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
3472 }
3473 LOG(HeapSampleJSConstructorEvent(*s_name,
3474 number_and_size.number(),
3475 number_and_size.bytes()));
3476 }
3477
3478
3479 void JSConstructorProfile::CollectStats(JSObject* obj) {
3480 String* constructor_func = NULL;
3481 if (obj->map()->constructor()->IsJSFunction()) {
3482 JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
3483 SharedFunctionInfo* sfi = constructor->shared();
3484 String* name = String::cast(sfi->name());
3485 constructor_func = name->length() > 0 ? name : sfi->inferred_name();
3486 } else if (obj->IsJSFunction()) {
3487 constructor_func = Heap::function_class_symbol();
3488 }
3489 JSObjectsInfoTree::Locator loc;
3490 if (!js_objects_info_tree_.Find(constructor_func, &loc)) {
3491 js_objects_info_tree_.Insert(constructor_func, &loc);
3492 }
3493 NumberAndSizeInfo number_and_size = loc.value();
3494 number_and_size.increment_number(1);
3495 number_and_size.increment_bytes(CalculateJSObjectNetworkSize(obj));
3496 loc.set_value(number_and_size);
3497 }
3498
3499
3500 void JSConstructorProfile::PrintStats() {
3501 js_objects_info_tree_.ForEach(this);
3502 }
3503
3504 } // namespace
3505 #endif
3506
3507
3414 // 3508 //
3415 // HeapProfiler class implementation. 3509 // HeapProfiler class implementation.
3416 // 3510 //
3417 #ifdef ENABLE_LOGGING_AND_PROFILING 3511 #ifdef ENABLE_LOGGING_AND_PROFILING
3418 void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) { 3512 void HeapProfiler::CollectStats(HeapObject* obj, HistogramInfo* info) {
3419 InstanceType type = obj->map()->instance_type(); 3513 InstanceType type = obj->map()->instance_type();
3420 ASSERT(0 <= type && type <= LAST_TYPE); 3514 ASSERT(0 <= type && type <= LAST_TYPE);
3421 info[type].increment_number(1); 3515 info[type].increment_number(1);
3422 info[type].increment_bytes(obj->Size()); 3516 info[type].increment_bytes(obj->Size());
3423 } 3517 }
3424 #endif 3518 #endif
3425 3519
3426 3520
3427 #ifdef ENABLE_LOGGING_AND_PROFILING 3521 #ifdef ENABLE_LOGGING_AND_PROFILING
3428 void HeapProfiler::WriteSample() { 3522 void HeapProfiler::WriteSample() {
3429 LOG(HeapSampleBeginEvent("Heap", "allocated")); 3523 LOG(HeapSampleBeginEvent("Heap", "allocated"));
3430 LOG(HeapSampleStats( 3524 LOG(HeapSampleStats(
3431 "Heap", "allocated", Heap::Capacity(), Heap::SizeOfObjects())); 3525 "Heap", "allocated", Heap::Capacity(), Heap::SizeOfObjects()));
3432 3526
3433 HistogramInfo info[LAST_TYPE+1]; 3527 HistogramInfo info[LAST_TYPE+1];
3434 #define DEF_TYPE_NAME(name) info[name].set_name(#name); 3528 #define DEF_TYPE_NAME(name) info[name].set_name(#name);
3435 INSTANCE_TYPE_LIST(DEF_TYPE_NAME) 3529 INSTANCE_TYPE_LIST(DEF_TYPE_NAME)
3436 #undef DEF_TYPE_NAME 3530 #undef DEF_TYPE_NAME
3437 3531
3532 JSConstructorProfile js_cons_profile;
3438 HeapIterator iterator; 3533 HeapIterator iterator;
3439 while (iterator.has_next()) { 3534 while (iterator.has_next()) {
3440 CollectStats(iterator.next(), info); 3535 HeapObject* obj = iterator.next();
3536 CollectStats(obj, info);
3537 if (obj->IsJSObject()) {
3538 js_cons_profile.CollectStats(JSObject::cast(obj));
3539 }
3441 } 3540 }
3442 3541
3443 // Lump all the string types together. 3542 // Lump all the string types together.
3444 int string_number = 0; 3543 int string_number = 0;
3445 int string_bytes = 0; 3544 int string_bytes = 0;
3446 #define INCREMENT_SIZE(type, size, name, camel_name) \ 3545 #define INCREMENT_SIZE(type, size, name, camel_name) \
3447 string_number += info[type].number(); \ 3546 string_number += info[type].number(); \
3448 string_bytes += info[type].bytes(); 3547 string_bytes += info[type].bytes();
3449 STRING_TYPE_LIST(INCREMENT_SIZE) 3548 STRING_TYPE_LIST(INCREMENT_SIZE)
3450 #undef INCREMENT_SIZE 3549 #undef INCREMENT_SIZE
3451 if (string_bytes > 0) { 3550 if (string_bytes > 0) {
3452 LOG(HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes)); 3551 LOG(HeapSampleItemEvent("STRING_TYPE", string_number, string_bytes));
3453 } 3552 }
3454 3553
3455 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) { 3554 for (int i = FIRST_NONSTRING_TYPE; i <= LAST_TYPE; ++i) {
3456 if (info[i].bytes() > 0) { 3555 if (info[i].bytes() > 0) {
3457 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(), 3556 LOG(HeapSampleItemEvent(info[i].name(), info[i].number(),
3458 info[i].bytes())); 3557 info[i].bytes()));
3459 } 3558 }
3460 } 3559 }
3461 3560
3561 js_cons_profile.PrintStats();
3562
3462 LOG(HeapSampleEndEvent("Heap", "allocated")); 3563 LOG(HeapSampleEndEvent("Heap", "allocated"));
3463 } 3564 }
3464 3565
3465 3566
3466 #endif 3567 #endif
3467 3568
3468 3569
3469 3570
3470 #ifdef DEBUG 3571 #ifdef DEBUG
3471 3572
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
3738 #ifdef DEBUG 3839 #ifdef DEBUG
3739 bool Heap::GarbageCollectionGreedyCheck() { 3840 bool Heap::GarbageCollectionGreedyCheck() {
3740 ASSERT(FLAG_gc_greedy); 3841 ASSERT(FLAG_gc_greedy);
3741 if (Bootstrapper::IsActive()) return true; 3842 if (Bootstrapper::IsActive()) return true;
3742 if (disallow_allocation_failure()) return true; 3843 if (disallow_allocation_failure()) return true;
3743 return CollectGarbage(0, NEW_SPACE); 3844 return CollectGarbage(0, NEW_SPACE);
3744 } 3845 }
3745 #endif 3846 #endif
3746 3847
3747 } } // namespace v8::internal 3848 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/jsregexp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698