| 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 558 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 569 m_persistentFreed = 0; | 569 m_persistentFreed = 0; |
| 570 } | 570 } |
| 571 | 571 |
| 572 size_t ThreadState::currentObjectSize() | 572 size_t ThreadState::currentObjectSize() |
| 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::estimatedLiveObjectSize() |
| 578 { | 578 { |
| 579 if (Heap::persistentCountAtLastGC() == 0) { |
| 580 // We'll reach here only before hitting the first GC. |
| 581 return 0; |
| 582 } |
| 583 |
| 579 // We estimate the live object size with the following equations. | 584 // We estimate the live object size with the following equations. |
| 580 // | 585 // |
| 581 // heapSizePerPersistent = (marked(t0, t1) + partitionAlloc(t0)) / persist
entCount(t0) | 586 // heapSizePerPersistent = (marked(t0, t1) + partitionAlloc(t0)) / persist
entCount(t0) |
| 582 // estimatedLiveObjectSize = marked(t0, t) + allocated(t0, t) + partitionA
lloc(t) - heapSizePerPersistent * collectedPersistentCount(t0, t) | 587 // estimatedLiveObjectSize = marked(t0, t) + allocated(t0, t) + partitionA
lloc(t) - heapSizePerPersistent * collectedPersistentCount(t0, t) |
| 583 // | 588 // |
| 584 // t0: The time when the last collectGarbage runs. | 589 // t0: The time when the last collectGarbage runs. |
| 585 // t1: The time when the last completeSweep runs. | 590 // t1: The time when the last completeSweep runs. |
| 586 // t: The current time. | 591 // t: The current time. |
| 587 // marked(t0, t): The size of marked objects between t0 and t. | 592 // marked(t0, t): The size of marked objects between t0 and t. |
| 588 // allocated(t0, t): The size of newly allocated objects between t0 and t. | 593 // allocated(t0, t): The size of newly allocated objects between t0 and t. |
| 589 // persistentCount(t): The number of existing persistent handles at t. | 594 // persistentCount(t): The number of existing persistent handles at t. |
| 590 // collectedPersistentCount(t0, t): | 595 // collectedPersistentCount(t0, t): |
| 591 // The number of persistent handles collected between | 596 // The number of persistent handles collected between |
| 592 // t0 and t. | 597 // t0 and t. |
| 593 // partitionAlloc(t): The size of allocated memory in PartitionAlloc at 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()); |
| 594 size_t currentHeapSize = currentObjectSize(); | 600 size_t currentHeapSize = currentObjectSize(); |
| 595 size_t heapSizeRetainedByCollectedPersistents = Heap::heapSizePerPersistent(
) * Heap::collectedPersistentCount(); | 601 if (currentHeapSize < heapSizeRetainedByCollectedPersistents) |
| 596 size_t estimatedSize = 0; | 602 return 0; |
| 597 if (currentHeapSize > heapSizeRetainedByCollectedPersistents) | 603 return currentHeapSize - heapSizeRetainedByCollectedPersistents; |
| 598 estimatedSize = currentHeapSize - heapSizeRetainedByCollectedPersistents
; | |
| 599 return estimatedSize; | |
| 600 } | 604 } |
| 601 | 605 |
| 602 double ThreadState::heapGrowingRate() | 606 double ThreadState::heapGrowingRate() |
| 603 { | 607 { |
| 604 size_t currentSize = currentObjectSize(); | 608 size_t currentSize = currentObjectSize(); |
| 605 size_t estimatedSize = estimatedLiveObjectSize(); | 609 size_t estimatedSize = estimatedLiveObjectSize(); |
| 606 double growingRate = 1.0 * currentSize / estimatedSize; | 610 // If the estimatedSize is 0, we set a very high growing rate |
| 611 // to trigger a GC. |
| 612 double growingRate = estimatedSize > 0 ? 1.0 * currentSize / estimatedSize :
100; |
| 607 TRACE_COUNTER1("blink_gc", "ThreadState::currentHeapSizeKB", std::min(curren
tSize / 1024, static_cast<size_t>(INT_MAX))); | 613 TRACE_COUNTER1("blink_gc", "ThreadState::currentHeapSizeKB", std::min(curren
tSize / 1024, static_cast<size_t>(INT_MAX))); |
| 608 TRACE_COUNTER1("blink_gc", "ThreadState::estimatedLiveObjectSizeKB", std::mi
n(estimatedSize / 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))); |
| 609 TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>(
100 * growingRate)); | 615 TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>(
100 * growingRate)); |
| 610 return growingRate; | 616 return growingRate; |
| 611 } | 617 } |
| 612 | 618 |
| 613 // TODO(haraken): We should improve the GC heuristics. | 619 // TODO(haraken): We should improve the GC heuristics. |
| 614 // The heuristics affect performance significantly. | 620 // The heuristics affect performance significantly. |
| 615 bool ThreadState::judgeGCThreshold(size_t allocatedObjectSizeThreshold, double h
eapGrowingRateThreshold) | 621 bool ThreadState::judgeGCThreshold(size_t allocatedObjectSizeThreshold, double h
eapGrowingRateThreshold) |
| 616 { | 622 { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 return false; | 654 return false; |
| 649 #if ENABLE(IDLE_GC) | 655 #if ENABLE(IDLE_GC) |
| 650 return false; | 656 return false; |
| 651 #else | 657 #else |
| 652 return judgeGCThreshold(1024 * 1024, 1.5); | 658 return judgeGCThreshold(1024 * 1024, 1.5); |
| 653 #endif | 659 #endif |
| 654 } | 660 } |
| 655 | 661 |
| 656 bool ThreadState::shouldSchedulePageNavigationGC(float estimatedRemovalRatio) | 662 bool ThreadState::shouldSchedulePageNavigationGC(float estimatedRemovalRatio) |
| 657 { | 663 { |
| 658 if (isGCForbidden()) | |
| 659 return false; | |
| 660 | |
| 661 return judgeGCThreshold(1024 * 1024, 1.5); | 664 return judgeGCThreshold(1024 * 1024, 1.5); |
| 662 } | 665 } |
| 663 | 666 |
| 664 bool ThreadState::shouldForceConservativeGC() | 667 bool ThreadState::shouldForceConservativeGC() |
| 665 { | 668 { |
| 666 if (isGCForbidden()) | |
| 667 return false; | |
| 668 | |
| 669 // TODO(haraken): 400% is too large. Lower the heap growing factor. | 669 // TODO(haraken): 400% is too large. Lower the heap growing factor. |
| 670 return judgeGCThreshold(32 * 1024 * 1024, 5.0); | 670 return judgeGCThreshold(32 * 1024 * 1024, 5.0); |
| 671 } | 671 } |
| 672 | 672 |
| 673 void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio) | 673 void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio) |
| 674 { | 674 { |
| 675 ASSERT(checkThread()); | 675 ASSERT(checkThread()); |
| 676 if (isGCForbidden()) |
| 677 return; |
| 678 |
| 676 // Finish on-going lazy sweeping. | 679 // Finish on-going lazy sweeping. |
| 677 // TODO(haraken): It might not make sense to force completeSweep() for all | 680 // TODO(haraken): It might not make sense to force completeSweep() for all |
| 678 // page navigations. | 681 // page navigations. |
| 679 completeSweep(); | 682 completeSweep(); |
| 680 ASSERT(!isSweepingInProgress()); | 683 ASSERT(!isSweepingInProgress()); |
| 681 ASSERT(!sweepForbidden()); | 684 ASSERT(!sweepForbidden()); |
| 682 | 685 |
| 683 Heap::reportMemoryUsageForTracing(); | 686 Heap::reportMemoryUsageForTracing(); |
| 684 if (shouldSchedulePageNavigationGC(estimatedRemovalRatio)) | 687 if (shouldSchedulePageNavigationGC(estimatedRemovalRatio)) |
| 685 schedulePageNavigationGC(); | 688 schedulePageNavigationGC(); |
| 686 } | 689 } |
| 687 | 690 |
| 688 void ThreadState::schedulePageNavigationGC() | 691 void ThreadState::schedulePageNavigationGC() |
| 689 { | 692 { |
| 690 ASSERT(checkThread()); | 693 ASSERT(checkThread()); |
| 691 ASSERT(!isSweepingInProgress()); | 694 ASSERT(!isSweepingInProgress()); |
| 692 setGCState(PageNavigationGCScheduled); | 695 setGCState(PageNavigationGCScheduled); |
| 693 } | 696 } |
| 694 | 697 |
| 695 void ThreadState::scheduleGCIfNeeded() | 698 void ThreadState::scheduleGCIfNeeded() |
| 696 { | 699 { |
| 697 ASSERT(checkThread()); | 700 ASSERT(checkThread()); |
| 701 if (isGCForbidden()) |
| 702 return; |
| 703 |
| 698 // Allocation is allowed during sweeping, but those allocations should not | 704 // Allocation is allowed during sweeping, but those allocations should not |
| 699 // trigger nested GCs. | 705 // trigger nested GCs. |
| 700 if (isSweepingInProgress()) | 706 if (isSweepingInProgress()) |
| 701 return; | 707 return; |
| 702 ASSERT(!sweepForbidden()); | 708 ASSERT(!sweepForbidden()); |
| 703 | 709 |
| 704 Heap::reportMemoryUsageForTracing(); | 710 Heap::reportMemoryUsageForTracing(); |
| 705 | 711 |
| 706 if (shouldForceMemoryPressureGC()) { | 712 if (shouldForceMemoryPressureGC()) { |
| 707 Heap::collectGarbage(HeapPointersOnStack, GCWithoutSweep, Heap::Conserva
tiveGC); | 713 Heap::collectGarbage(HeapPointersOnStack, GCWithoutSweep, Heap::Conserva
tiveGC); |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 { | 1145 { |
| 1140 ASSERT(checkThread()); | 1146 ASSERT(checkThread()); |
| 1141 Heap::reportMemoryUsageForTracing(); | 1147 Heap::reportMemoryUsageForTracing(); |
| 1142 | 1148 |
| 1143 if (isMainThread()) { | 1149 if (isMainThread()) { |
| 1144 double collectionRate = 0; | 1150 double collectionRate = 0; |
| 1145 if (Heap::objectSizeAtLastGC() > 0) | 1151 if (Heap::objectSizeAtLastGC() > 0) |
| 1146 collectionRate = 1 - 1.0 * Heap::markedObjectSize() / Heap::objectSi
zeAtLastGC(); | 1152 collectionRate = 1 - 1.0 * Heap::markedObjectSize() / Heap::objectSi
zeAtLastGC(); |
| 1147 TRACE_COUNTER1("blink_gc", "ThreadState::collectionRate", static_cast<in
t>(100 * collectionRate)); | 1153 TRACE_COUNTER1("blink_gc", "ThreadState::collectionRate", static_cast<in
t>(100 * collectionRate)); |
| 1148 | 1154 |
| 1149 // See the comment in estimatedLiveObjectSize() for what we're | |
| 1150 // calculating here. | |
| 1151 // | |
| 1152 // Heap::markedObjectSize() may be underestimated here if any other | 1155 // Heap::markedObjectSize() may be underestimated here if any other |
| 1153 // thread has not yet finished lazy sweeping. | 1156 // thread has not yet finished lazy sweeping. |
| 1154 if (Heap::persistentCountAtLastGC() > 0) { | 1157 Heap::setMarkedObjectSizeAtLastCompleteSweep(Heap::markedObjectSize()); |
| 1155 Heap::setHeapSizePerPersistent((Heap::markedObjectSize() + Heap::par
titionAllocSizeAtLastGC()) / Heap::persistentCountAtLastGC()); | |
| 1156 } | |
| 1157 } | 1158 } |
| 1158 | 1159 |
| 1159 switch (gcState()) { | 1160 switch (gcState()) { |
| 1160 case Sweeping: | 1161 case Sweeping: |
| 1161 setGCState(NoGCScheduled); | 1162 setGCState(NoGCScheduled); |
| 1162 break; | 1163 break; |
| 1163 case SweepingAndPreciseGCScheduled: | 1164 case SweepingAndPreciseGCScheduled: |
| 1164 setGCState(PreciseGCScheduled); | 1165 setGCState(PreciseGCScheduled); |
| 1165 break; | 1166 break; |
| 1166 case SweepingAndIdleGCScheduled: | 1167 case SweepingAndIdleGCScheduled: |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1584 json->beginArray(it->key.ascii().data()); | 1585 json->beginArray(it->key.ascii().data()); |
| 1585 for (size_t age = 0; age <= maxHeapObjectAge; ++age) | 1586 for (size_t age = 0; age <= maxHeapObjectAge; ++age) |
| 1586 json->pushInteger(it->value.ages[age]); | 1587 json->pushInteger(it->value.ages[age]); |
| 1587 json->endArray(); | 1588 json->endArray(); |
| 1588 } | 1589 } |
| 1589 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s
tatsName, this, json.release()); | 1590 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s
tatsName, this, json.release()); |
| 1590 } | 1591 } |
| 1591 #endif | 1592 #endif |
| 1592 | 1593 |
| 1593 } // namespace blink | 1594 } // namespace blink |
| OLD | NEW |