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

Side by Side Diff: src/profile-generator.cc

Issue 10086004: Add size metric into Heap Stats. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: comments addressed Created 8 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1; 1305 const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1;
1306 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId = 1306 const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId =
1307 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep; 1307 HeapObjectsMap::kInternalRootObjectId + HeapObjectsMap::kObjectIdStep;
1308 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId = 1308 const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId =
1309 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep; 1309 HeapObjectsMap::kGcRootsObjectId + HeapObjectsMap::kObjectIdStep;
1310 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId = 1310 const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId =
1311 HeapObjectsMap::kGcRootsFirstSubrootId + 1311 HeapObjectsMap::kGcRootsFirstSubrootId +
1312 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep; 1312 VisitorSynchronization::kNumberOfSyncTags * HeapObjectsMap::kObjectIdStep;
1313 1313
1314 HeapObjectsMap::HeapObjectsMap() 1314 HeapObjectsMap::HeapObjectsMap()
1315 : initial_fill_mode_(true), 1315 : next_id_(kFirstAvailableObjectId),
1316 next_id_(kFirstAvailableObjectId),
1317 entries_map_(AddressesMatch), 1316 entries_map_(AddressesMatch),
1318 entries_(new List<EntryInfo>()) { 1317 entries_(new List<EntryInfo>()) {
1319 // This dummy element solves a problem with entries_map_. 1318 // This dummy element solves a problem with entries_map_.
1320 // When we do lookup in HashMap we see no difference between two cases: 1319 // When we do lookup in HashMap we see no difference between two cases:
1321 // it has an entry with NULL as the value or it has created 1320 // it has an entry with NULL as the value or it has created
1322 // a new entry on the fly with NULL as the default value. 1321 // a new entry on the fly with NULL as the default value.
1323 // With such dummy element we have a guaranty that all entries_map_ entries 1322 // With such dummy element we have a guaranty that all entries_map_ entries
1324 // will have the value field grater than 0. 1323 // will have the value field grater than 0.
1325 // This fact is using in MoveObject method. 1324 // This fact is using in MoveObject method.
1326 entries_->Add(EntryInfo(0, NULL)); 1325 entries_->Add(EntryInfo(0, NULL, 0));
1327 } 1326 }
1328 1327
1329 1328
1330 HeapObjectsMap::~HeapObjectsMap() { 1329 HeapObjectsMap::~HeapObjectsMap() {
1331 delete entries_; 1330 delete entries_;
1332 } 1331 }
1333 1332
1334 1333
1335 void HeapObjectsMap::SnapshotGenerationFinished() { 1334 void HeapObjectsMap::SnapshotGenerationFinished() {
1336 initial_fill_mode_ = false;
1337 RemoveDeadEntries(); 1335 RemoveDeadEntries();
1338 } 1336 }
1339 1337
1340 1338
1341 SnapshotObjectId HeapObjectsMap::FindObject(Address addr) {
1342 if (!initial_fill_mode_) {
1343 SnapshotObjectId existing = FindEntry(addr);
1344 if (existing != 0) return existing;
1345 }
1346 SnapshotObjectId id = next_id_;
1347 next_id_ += kObjectIdStep;
1348 AddEntry(addr, id);
1349 // Here and in other places the length of entries_ list has to be
1350 // the same or greater than the length of entries_map_. But entries_ list
1351 // has a dummy element at index 0.
1352 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
1353 return id;
1354 }
1355
1356
1357 void HeapObjectsMap::MoveObject(Address from, Address to) { 1339 void HeapObjectsMap::MoveObject(Address from, Address to) {
1358 ASSERT(to != NULL); 1340 ASSERT(to != NULL);
1359 ASSERT(from != NULL); 1341 ASSERT(from != NULL);
1360 if (from == to) return; 1342 if (from == to) return;
1361 void* from_value = entries_map_.Remove(from, AddressHash(from)); 1343 void* from_value = entries_map_.Remove(from, AddressHash(from));
1362 if (from_value == NULL) return; 1344 if (from_value == NULL) return;
1363 int from_entry_info_index = 1345 int from_entry_info_index =
1364 static_cast<int>(reinterpret_cast<intptr_t>(from_value)); 1346 static_cast<int>(reinterpret_cast<intptr_t>(from_value));
1365 entries_->at(from_entry_info_index).addr = to; 1347 entries_->at(from_entry_info_index).addr = to;
1366 HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true); 1348 HashMap::Entry* to_entry = entries_map_.Lookup(to, AddressHash(to), true);
1367 if (to_entry->value != NULL) { 1349 if (to_entry->value != NULL) {
1368 int to_entry_info_index = 1350 int to_entry_info_index =
1369 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value)); 1351 static_cast<int>(reinterpret_cast<intptr_t>(to_entry->value));
1370 // Without this operation we will have two EntryInfo's with the same 1352 // Without this operation we will have two EntryInfo's with the same
1371 // value in addr field. It is bad because later at RemoveDeadEntries 1353 // value in addr field. It is bad because later at RemoveDeadEntries
1372 // one of this entry will be removed with the corresponding entries_map_ 1354 // one of this entry will be removed with the corresponding entries_map_
1373 // entry. 1355 // entry.
1374 entries_->at(to_entry_info_index).addr = NULL; 1356 entries_->at(to_entry_info_index).addr = NULL;
1375 } 1357 }
1376 to_entry->value = reinterpret_cast<void*>(from_entry_info_index); 1358 to_entry->value = reinterpret_cast<void*>(from_entry_info_index);
1377 } 1359 }
1378 1360
1379 1361
1380 void HeapObjectsMap::AddEntry(Address addr, SnapshotObjectId id) {
1381 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true);
1382 ASSERT(entry->value == NULL);
1383 ASSERT(entries_->length() > 0 &&
1384 entries_->at(0).id == 0 &&
1385 entries_->at(0).addr == NULL);
1386 ASSERT(entries_->at(entries_->length() - 1).id < id);
1387 entry->value = reinterpret_cast<void*>(entries_->length());
1388 entries_->Add(EntryInfo(id, addr));
1389 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
1390 }
1391
1392
1393 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) { 1362 SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) {
1394 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false); 1363 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), false);
1395 if (entry != NULL) { 1364 if (entry == NULL) return 0;
1396 int entry_index = 1365 int entry_index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1397 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 1366 EntryInfo& entry_info = entries_->at(entry_index);
1398 EntryInfo& entry_info = entries_->at(entry_index); 1367 entry_info.accessed = true;
1399 entry_info.accessed = true; 1368 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
1400 ASSERT(static_cast<uint32_t>(entries_->length()) > 1369 return entry_info.id;
1401 entries_map_.occupancy());
1402 return entry_info.id;
1403 } else {
1404 return 0;
1405 }
1406 } 1370 }
1407 1371
1408 1372
1409 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr) { 1373 SnapshotObjectId HeapObjectsMap::FindOrAddEntry(Address addr,
1374 unsigned int size) {
1410 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); 1375 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
1411 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true); 1376 HashMap::Entry* entry = entries_map_.Lookup(addr, AddressHash(addr), true);
1412 if (entry->value != NULL) { 1377 if (entry->value != NULL) {
1413 int entry_index = 1378 int entry_index =
1414 static_cast<int>(reinterpret_cast<intptr_t>(entry->value)); 1379 static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
1415 EntryInfo& entry_info = entries_->at(entry_index); 1380 EntryInfo& entry_info = entries_->at(entry_index);
1416 entry_info.accessed = true; 1381 entry_info.accessed = true;
1382 entry_info.size = size;
1417 return entry_info.id; 1383 return entry_info.id;
1418 } 1384 }
1419 entry->value = reinterpret_cast<void*>(entries_->length()); 1385 entry->value = reinterpret_cast<void*>(entries_->length());
1420 SnapshotObjectId id = next_id_; 1386 SnapshotObjectId id = next_id_;
1421 next_id_ += kObjectIdStep; 1387 next_id_ += kObjectIdStep;
1422 entries_->Add(EntryInfo(id, addr)); 1388 entries_->Add(EntryInfo(id, addr, size));
1423 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy()); 1389 ASSERT(static_cast<uint32_t>(entries_->length()) > entries_map_.occupancy());
1424 return id; 1390 return id;
1425 } 1391 }
1426 1392
1427 1393
1428 void HeapObjectsMap::StopHeapObjectsTracking() { 1394 void HeapObjectsMap::StopHeapObjectsTracking() {
1429 time_intervals_.Clear(); 1395 time_intervals_.Clear();
1430 } 1396 }
1431 1397
1432 void HeapObjectsMap::UpdateHeapObjectsMap() { 1398 void HeapObjectsMap::UpdateHeapObjectsMap() {
1433 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, 1399 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1434 "HeapSnapshotsCollection::UpdateHeapObjectsMap"); 1400 "HeapSnapshotsCollection::UpdateHeapObjectsMap");
1435 HeapIterator iterator(HeapIterator::kFilterUnreachable); 1401 HeapIterator iterator;
1436 for (HeapObject* obj = iterator.next(); 1402 for (HeapObject* obj = iterator.next();
1437 obj != NULL; 1403 obj != NULL;
1438 obj = iterator.next()) { 1404 obj = iterator.next()) {
1439 FindOrAddEntry(obj->address()); 1405 FindOrAddEntry(obj->address(), obj->Size());
1440 } 1406 }
1441 initial_fill_mode_ = false;
1442 RemoveDeadEntries(); 1407 RemoveDeadEntries();
1443 } 1408 }
1444 1409
1445 1410
1446 void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) { 1411 void HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream) {
1447 UpdateHeapObjectsMap(); 1412 UpdateHeapObjectsMap();
1448 time_intervals_.Add(TimeInterval(next_id_)); 1413 time_intervals_.Add(TimeInterval(next_id_));
1449 int prefered_chunk_size = stream->GetChunkSize(); 1414 int prefered_chunk_size = stream->GetChunkSize();
1450 List<uint32_t> stats_buffer; 1415 List<uint32_t> stats_buffer;
1451 ASSERT(!entries_->is_empty()); 1416 ASSERT(!entries_->is_empty());
1452 EntryInfo* entry_info = &entries_->first(); 1417 EntryInfo* entry_info = &entries_->first();
1453 EntryInfo* end_entry_info = &entries_->last() + 1; 1418 EntryInfo* end_entry_info = &entries_->last() + 1;
1454 for (int time_interval_index = 0; 1419 for (int time_interval_index = 0;
1455 time_interval_index < time_intervals_.length(); 1420 time_interval_index < time_intervals_.length();
1456 ++time_interval_index) { 1421 ++time_interval_index) {
1457 TimeInterval& time_interval = time_intervals_[time_interval_index]; 1422 TimeInterval& time_interval = time_intervals_[time_interval_index];
1458 SnapshotObjectId time_interval_id = time_interval.id; 1423 SnapshotObjectId time_interval_id = time_interval.id;
1459 uint32_t entries_count = 0; 1424 uint32_t entries_size = 0;
1425 EntryInfo* start_entry_info = entry_info;
1460 while (entry_info < end_entry_info && entry_info->id < time_interval_id) { 1426 while (entry_info < end_entry_info && entry_info->id < time_interval_id) {
1461 ++entries_count; 1427 entries_size += entry_info->size;
1462 ++entry_info; 1428 ++entry_info;
1463 } 1429 }
1464 if (time_interval.count != entries_count) { 1430 uint32_t entries_count =
1431 static_cast<uint32_t>(entry_info - start_entry_info);
1432 if (time_interval.count != entries_count ||
1433 time_interval.size != entries_size) {
1465 stats_buffer.Add(time_interval_index); 1434 stats_buffer.Add(time_interval_index);
1466 stats_buffer.Add(time_interval.count = entries_count); 1435 stats_buffer.Add(time_interval.count = entries_count);
1436 stats_buffer.Add(time_interval.size = entries_size);
1467 if (stats_buffer.length() >= prefered_chunk_size) { 1437 if (stats_buffer.length() >= prefered_chunk_size) {
1468 OutputStream::WriteResult result = stream->WriteUint32Chunk( 1438 OutputStream::WriteResult result = stream->WriteUint32Chunk(
1469 &stats_buffer.first(), stats_buffer.length()); 1439 &stats_buffer.first(), stats_buffer.length());
1470 if (result == OutputStream::kAbort) return; 1440 if (result == OutputStream::kAbort) return;
1471 stats_buffer.Clear(); 1441 stats_buffer.Clear();
1472 } 1442 }
1473 } 1443 }
1474 } 1444 }
1475 ASSERT(entry_info == end_entry_info); 1445 ASSERT(entry_info == end_entry_info);
1476 if (!stats_buffer.is_empty()) { 1446 if (!stats_buffer.is_empty()) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1587 // First perform a full GC in order to avoid dead objects. 1557 // First perform a full GC in order to avoid dead objects.
1588 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask, 1558 HEAP->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1589 "HeapSnapshotsCollection::FindHeapObjectById"); 1559 "HeapSnapshotsCollection::FindHeapObjectById");
1590 AssertNoAllocation no_allocation; 1560 AssertNoAllocation no_allocation;
1591 HeapObject* object = NULL; 1561 HeapObject* object = NULL;
1592 HeapIterator iterator(HeapIterator::kFilterUnreachable); 1562 HeapIterator iterator(HeapIterator::kFilterUnreachable);
1593 // Make sure that object with the given id is still reachable. 1563 // Make sure that object with the given id is still reachable.
1594 for (HeapObject* obj = iterator.next(); 1564 for (HeapObject* obj = iterator.next();
1595 obj != NULL; 1565 obj != NULL;
1596 obj = iterator.next()) { 1566 obj = iterator.next()) {
1597 if (ids_.FindObject(obj->address()) == id) { 1567 if (ids_.FindEntry(obj->address()) == id) {
1598 ASSERT(object == NULL); 1568 ASSERT(object == NULL);
1599 object = obj; 1569 object = obj;
1600 // Can't break -- kFilterUnreachable requires full heap traversal. 1570 // Can't break -- kFilterUnreachable requires full heap traversal.
1601 } 1571 }
1602 } 1572 }
1603 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>(); 1573 return object != NULL ? Handle<HeapObject>(object) : Handle<HeapObject>();
1604 } 1574 }
1605 1575
1606 1576
1607 HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder = 1577 HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder =
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
1888 children_count, 1858 children_count,
1889 retainers_count); 1859 retainers_count);
1890 } 1860 }
1891 1861
1892 1862
1893 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object, 1863 HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1894 HeapEntry::Type type, 1864 HeapEntry::Type type,
1895 const char* name, 1865 const char* name,
1896 int children_count, 1866 int children_count,
1897 int retainers_count) { 1867 int retainers_count) {
1868 int object_size = object->Size();
1869 SnapshotObjectId object_id =
1870 collection_->GetObjectId(object->address(), object_size);
1898 return snapshot_->AddEntry(type, 1871 return snapshot_->AddEntry(type,
1899 name, 1872 name,
1900 collection_->GetObjectId(object->address()), 1873 object_id,
1901 object->Size(), 1874 object_size,
1902 children_count, 1875 children_count,
1903 retainers_count); 1876 retainers_count);
1904 } 1877 }
1905 1878
1906 1879
1907 class GcSubrootsEnumerator : public ObjectVisitor { 1880 class GcSubrootsEnumerator : public ObjectVisitor {
1908 public: 1881 public:
1909 GcSubrootsEnumerator( 1882 GcSubrootsEnumerator(
1910 SnapshotFillerInterface* filler, V8HeapExplorer* explorer) 1883 SnapshotFillerInterface* filler, V8HeapExplorer* explorer)
1911 : filler_(filler), 1884 : filler_(filler),
(...skipping 1950 matching lines...) Expand 10 before | Expand all | Expand 10 after
3862 3835
3863 3836
3864 void HeapSnapshotJSONSerializer::SortHashMap( 3837 void HeapSnapshotJSONSerializer::SortHashMap(
3865 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3838 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
3866 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3839 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
3867 sorted_entries->Add(p); 3840 sorted_entries->Add(p);
3868 sorted_entries->Sort(SortUsingEntryValue); 3841 sorted_entries->Sort(SortUsingEntryValue);
3869 } 3842 }
3870 3843
3871 } } // namespace v8::internal 3844 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698