Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 
| 3 * | 3 * | 
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without | 
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are | 
| 6 * met: | 6 * met: | 
| 7 * | 7 * | 
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright | 
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. | 
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above | 
| (...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 562 { | 562 { | 
| 563 if (m_persistentAllocated >= m_persistentFreed) | 563 if (m_persistentAllocated >= m_persistentFreed) | 
| 564 Heap::increasePersistentCount(m_persistentAllocated - m_persistentFreed) ; | 564 Heap::increasePersistentCount(m_persistentAllocated - m_persistentFreed) ; | 
| 565 else | 565 else | 
| 566 Heap::decreasePersistentCount(m_persistentFreed - m_persistentAllocated) ; | 566 Heap::decreasePersistentCount(m_persistentFreed - m_persistentAllocated) ; | 
| 567 Heap::increaseCollectedPersistentCount(m_persistentFreed); | 567 Heap::increaseCollectedPersistentCount(m_persistentFreed); | 
| 568 m_persistentAllocated = 0; | 568 m_persistentAllocated = 0; | 
| 569 m_persistentFreed = 0; | 569 m_persistentFreed = 0; | 
| 570 } | 570 } | 
| 571 | 571 | 
| 572 size_t ThreadState::currentObjectSize() | 572 size_t ThreadState::totalMemorySize() | 
| 573 { | 573 { | 
| 574 return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partiti ons::totalSizeOfCommittedPages(); | 574 return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partiti ons::totalSizeOfCommittedPages(); | 
| 575 } | 575 } | 
| 576 | 576 | 
| 577 size_t ThreadState::estimatedLiveObjectSize() | 577 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, size_t sizeAtLa stGC) | 
| 578 { | 578 { | 
| 579 if (Heap::persistentCountAtLastGC() == 0) { | 579 if (Heap::persistentCountAtLastGC() == 0) { | 
| 580 // We'll reach here only before hitting the first GC. | 580 // We'll reach here only before hitting the first GC. | 
| 581 return 0; | 581 return 0; | 
| 582 } | 582 } | 
| 583 | 583 | 
| 584 // We estimate the live object size with the following equations. | 584 // (estimated size) = (estimation base size) - (heap size at the last GC) / (# of persistent handles at the last GC) * (# of persistent handles collected si nce the last GC); | 
| 585 // | 585 size_t sizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * sizeAt LastGC / Heap::persistentCountAtLastGC() * Heap::collectedPersistentCount()); | 
| 586 // heapSizePerPersistent = (marked(t0, t1) + partitionAlloc(t0)) / persist entCount(t0) | 586 if (estimationBaseSize < sizeRetainedByCollectedPersistents) | 
| 587 // estimatedLiveObjectSize = marked(t0, t) + allocated(t0, t) + partitionA lloc(t) - heapSizePerPersistent * collectedPersistentCount(t0, t) | |
| 588 // | |
| 589 // t0: The time when the last collectGarbage runs. | |
| 590 // t1: The time when the last completeSweep runs. | |
| 591 // t: The current time. | |
| 592 // marked(t0, t): The size of marked objects between t0 and t. | |
| 593 // allocated(t0, t): The size of newly allocated objects between t0 and t. | |
| 594 // persistentCount(t): The number of existing persistent handles at t. | |
| 595 // collectedPersistentCount(t0, t): | |
| 596 // The number of persistent handles collected between | |
| 597 // t0 and t. | |
| 598 // partitionAlloc(t): The size of allocated memory in PartitionAlloc at t. | |
| 599 size_t heapSizeRetainedByCollectedPersistents = static_cast<size_t>(1.0 * (H eap::markedObjectSizeAtLastCompleteSweep() + Heap::partitionAllocSizeAtLastGC()) / Heap::persistentCountAtLastGC() * Heap::collectedPersistentCount()); | |
| 600 size_t currentHeapSize = currentObjectSize(); | |
| 601 if (currentHeapSize < heapSizeRetainedByCollectedPersistents) | |
| 602 return 0; | 587 return 0; | 
| 603 return currentHeapSize - heapSizeRetainedByCollectedPersistents; | 588 return estimationBaseSize - sizeRetainedByCollectedPersistents; | 
| 604 } | 589 } | 
| 605 | 590 | 
| 606 double ThreadState::heapGrowingRate() | 591 double ThreadState::heapGrowingRate() | 
| 607 { | 592 { | 
| 608 size_t currentSize = currentObjectSize(); | 593 size_t currentSize = Heap::allocatedObjectSize() + Heap::markedObjectSize(); | 
| 609 size_t estimatedSize = estimatedLiveObjectSize(); | 594 size_t estimatedSize = estimatedLiveSize(Heap::markedObjectSizeAtLastComplet eSweep(), Heap::markedObjectSizeAtLastCompleteSweep()); | 
| 610 // If the estimatedSize is 0, we set a very high growing rate | 595 | 
| 611 // to trigger a GC. | 596 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. | 
| 612 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; | 597 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; | 
| 613 TRACE_COUNTER1("blink_gc", "ThreadState::currentHeapSizeKB", std::min(curren tSize / 1024, static_cast<size_t>(INT_MAX))); | 598 TRACE_COUNTER1("blink_gc", "ThreadState::heapEstimatedSizeKB", std::min(esti matedSize / 1024, static_cast<size_t>(INT_MAX))); | 
| 614 TRACE_COUNTER1("blink_gc", "ThreadState::estimatedLiveObjectSizeKB", std::mi n(estimatedSize / 1024, static_cast<size_t>(INT_MAX))); | |
| 615 TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>( 100 * growingRate)); | 599 TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>( 100 * growingRate)); | 
| 616 return growingRate; | 600 return growingRate; | 
| 617 } | 601 } | 
| 618 | 602 | 
| 619 // TODO(haraken): We should improve the GC heuristics. | 603 double ThreadState::partitionAllocGrowingRate() | 
| 620 // The heuristics affect performance significantly. | 604 { | 
| 605 size_t currentSize = WTF::Partitions::totalSizeOfCommittedPages(); | |
| 606 size_t estimatedSize = estimatedLiveSize(currentSize, Heap::partitionAllocSi zeAtLastGC()); | |
| 607 | |
| 608 // If the estimatedSize is 0, we set a high growing rate to trigger a GC. | |
| 609 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize : 100; | |
| 610 TRACE_COUNTER1("blink_gc", "ThreadState::partitionAllocEstimatedSizeKB", std ::min(estimatedSize / 1024, static_cast<size_t>(INT_MAX))); | |
| 611 TRACE_COUNTER1("blink_gc", "ThreadState::partitionAllocGrowingRate", static_ cast<int>(100 * growingRate)); | |
| 612 return growingRate; | |
| 613 } | |
| 614 | |
| 615 // TODO(haraken): We should improve the GC heuristics. The heuristics affect | |
| 616 // performance significantly. | |
| 621 bool ThreadState::judgeGCThreshold(size_t allocatedObjectSizeThreshold, double h eapGrowingRateThreshold) | 617 bool ThreadState::judgeGCThreshold(size_t allocatedObjectSizeThreshold, double h eapGrowingRateThreshold) | 
| 622 { | 618 { | 
| 623 // If the allocated object size is small enough, don't trigger a GC. | 619 // If the allocated object size is small enough, don't trigger a GC. | 
| 624 if (Heap::allocatedObjectSize() < allocatedObjectSizeThreshold) | 620 if (Heap::allocatedObjectSize() < allocatedObjectSizeThreshold) | 
| 625 return false; | 621 return false; | 
| 626 // If the heap growing rate is large enough, trigger a GC. | 622 // If the growing rate of Oilpan's heap or PartitionAlloc is high enough, | 
| 627 return heapGrowingRate() >= heapGrowingRateThreshold; | 623 // trigger a GC. | 
| 624 return heapGrowingRate() >= heapGrowingRateThreshold || partitionAllocGrowin gRate() >= heapGrowingRateThreshold; | |
| 
 
haraken
2015/09/08 00:41:02
This is the key of this CL.
 
 | |
| 628 } | 625 } | 
| 629 | 626 | 
| 630 bool ThreadState::shouldForceMemoryPressureGC() | 627 bool ThreadState::shouldForceMemoryPressureGC() | 
| 631 { | 628 { | 
| 632 if (currentObjectSize() < 300 * 1024 * 1024) | 629 if (totalMemorySize() < 300 * 1024 * 1024) | 
| 633 return false; | 630 return false; | 
| 634 | 631 | 
| 635 // If we're consuming too much memory, trigger a conservative GC | 632 // If we're consuming too much memory, trigger a conservative GC | 
| 636 // aggressively. This is a safe guard to avoid OOM. | 633 // aggressively. This is a safe guard to avoid OOM. | 
| 637 return judgeGCThreshold(0, 1.5); | 634 return judgeGCThreshold(0, 1.5); | 
| 638 } | 635 } | 
| 639 | 636 | 
| 640 bool ThreadState::shouldScheduleIdleGC() | 637 bool ThreadState::shouldScheduleIdleGC() | 
| 641 { | 638 { | 
| 642 if (gcState() != NoGCScheduled) | 639 if (gcState() != NoGCScheduled) | 
| (...skipping 967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1610 json->beginArray(it->key.ascii().data()); | 1607 json->beginArray(it->key.ascii().data()); | 
| 1611 for (size_t age = 0; age <= maxHeapObjectAge; ++age) | 1608 for (size_t age = 0; age <= maxHeapObjectAge; ++age) | 
| 1612 json->pushInteger(it->value.ages[age]); | 1609 json->pushInteger(it->value.ages[age]); | 
| 1613 json->endArray(); | 1610 json->endArray(); | 
| 1614 } | 1611 } | 
| 1615 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release()); | 1612 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release()); | 
| 1616 } | 1613 } | 
| 1617 #endif | 1614 #endif | 
| 1618 | 1615 | 
| 1619 } // namespace blink | 1616 } // namespace blink | 
| OLD | NEW |