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

Side by Side Diff: Source/platform/heap/ThreadState.cpp

Issue 1287283002: Oilpan: Clean up code around GC heuristics (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 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 | Annotate | Revision Log
« no previous file with comments | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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()
573 {
574 return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partiti ons::totalSizeOfCommittedPages();
575 }
576
572 size_t ThreadState::estimatedLiveObjectSize() 577 size_t ThreadState::estimatedLiveObjectSize()
573 { 578 {
574 // We estimate the live object size with the following equations. 579 // We estimate the live object size with the following equations.
575 // 580 //
576 // heapSizePerPersistent = (marked(t0, t1) + partitionAlloc(t0)) / persist entCount(t0) 581 // heapSizePerPersistent = (marked(t0, t1) + partitionAlloc(t0)) / persist entCount(t0)
577 // estimatedLiveObjectSize = marked(t0, t) + allocated(t0, t) + partitionA lloc(t) - heapSizePerPersistent * collectedPersistentCount(t0, t) 582 // estimatedLiveObjectSize = marked(t0, t) + allocated(t0, t) + partitionA lloc(t) - heapSizePerPersistent * collectedPersistentCount(t0, t)
578 // 583 //
579 // t0: The time when the last collectGarbage runs. 584 // t0: The time when the last collectGarbage runs.
580 // t1: The time when the last completeSweep runs. 585 // t1: The time when the last completeSweep runs.
581 // t: The current time. 586 // t: The current time.
582 // marked(t0, t): The size of marked objects between t0 and t. 587 // marked(t0, t): The size of marked objects between t0 and t.
583 // allocated(t0, t): The size of newly allocated objects between t0 and t. 588 // allocated(t0, t): The size of newly allocated objects between t0 and t.
584 // persistentCount(t): The number of existing persistent handles at t. 589 // persistentCount(t): The number of existing persistent handles at t.
585 // collectedPersistentCount(t0, t): 590 // collectedPersistentCount(t0, t):
586 // The number of persistent handles collected between 591 // The number of persistent handles collected between
587 // t0 and t. 592 // t0 and t.
588 // partitionAlloc(t): The size of allocated memory in PartitionAlloc at t. 593 // partitionAlloc(t): The size of allocated memory in PartitionAlloc at t.
589 size_t currentHeapSize = currentObjectSize(); 594 size_t currentHeapSize = currentObjectSize();
590 size_t heapSizeRetainedByCollectedPersistents = Heap::heapSizePerPersistent( ) * Heap::collectedPersistentCount(); 595 size_t heapSizeRetainedByCollectedPersistents = Heap::heapSizePerPersistent( ) * Heap::collectedPersistentCount();
591 size_t estimatedSize = 0; 596 size_t estimatedSize = 0;
592 if (currentHeapSize > heapSizeRetainedByCollectedPersistents) 597 if (currentHeapSize > heapSizeRetainedByCollectedPersistents)
593 estimatedSize = currentHeapSize - heapSizeRetainedByCollectedPersistents ; 598 estimatedSize = currentHeapSize - heapSizeRetainedByCollectedPersistents ;
594 TRACE_COUNTER1("blink_gc", "ThreadState::currentHeapSizeKB", std::min(curren tHeapSize / 1024, static_cast<size_t>(INT_MAX)));
595 TRACE_COUNTER1("blink_gc", "ThreadState::estimatedLiveObjectSizeKB", std::mi n(estimatedSize / 1024, static_cast<size_t>(INT_MAX)));
596 TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>( 100.0 * currentHeapSize / estimatedSize));
597 return estimatedSize; 599 return estimatedSize;
598 } 600 }
599 601
600 size_t ThreadState::currentObjectSize() 602 double ThreadState::heapGrowingRate()
601 { 603 {
602 return Heap::allocatedObjectSize() + Heap::markedObjectSize() + WTF::Partiti ons::totalSizeOfCommittedPages(); 604 size_t currentSize = currentObjectSize();
605 size_t estimatedSize = estimatedLiveObjectSize();
606 double growingRate = 1.0 * currentSize / estimatedSize;
607 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)));
609 TRACE_COUNTER1("blink_gc", "ThreadState::heapGrowingRate", static_cast<int>( 100 * growingRate));
610 return growingRate;
611 }
612
613 // TODO(haraken): We should improve the GC heuristics.
614 // The heuristics affect performance significantly.
615 bool ThreadState::judgeGCThreshold(size_t allocatedObjectSizeThreshold, double h eapGrowingRateThreshold)
616 {
617 // If the allocated object size is small enough, don't trigger a GC.
618 if (Heap::allocatedObjectSize() < allocatedObjectSizeThreshold)
619 return false;
620 // If the heap growing rate is large enough, trigger a GC.
621 return heapGrowingRate() >= heapGrowingRateThreshold;
603 } 622 }
604 623
605 bool ThreadState::shouldForceMemoryPressureGC() 624 bool ThreadState::shouldForceMemoryPressureGC()
606 { 625 {
607 // Avoid potential overflow by truncating to Kb. 626 if (currentObjectSize() < 300 * 1024 * 1024)
608 size_t currentObjectSizeKb = currentObjectSize() >> 10;
609 if (currentObjectSizeKb < 300 * 1024)
610 return false; 627 return false;
611 628
612 size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
613 // If we're consuming too much memory, trigger a conservative GC 629 // If we're consuming too much memory, trigger a conservative GC
614 // aggressively. This is a safe guard to avoid OOM. 630 // aggressively. This is a safe guard to avoid OOM.
615 return currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2; 631 return judgeGCThreshold(0, 1.5);
616 } 632 }
617 633
618 // TODO(haraken): We should improve the GC heuristics.
619 // These heuristics affect performance significantly.
620 bool ThreadState::shouldScheduleIdleGC() 634 bool ThreadState::shouldScheduleIdleGC()
621 { 635 {
622 if (gcState() != NoGCScheduled) 636 if (gcState() != NoGCScheduled)
623 return false; 637 return false;
624 #if ENABLE(IDLE_GC) 638 #if ENABLE(IDLE_GC)
625 // Avoid potential overflow by truncating to Kb. 639 return judgeGCThreshold(1024 * 1024, 1.5);
626 size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
627 // The estimated size is updated when the main thread finishes lazy
628 // sweeping. If this thread reaches here before the main thread finishes
629 // lazy sweeping, the thread will use the estimated size of the last GC.
630 size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
631 // Heap::markedObjectSize() may be underestimated if any thread has not
632 // finished completeSweep().
633 size_t currentObjectSizeKb = currentObjectSize() >> 10;
634 // Schedule an idle GC if Oilpan has allocated more than 1 MB since
635 // the last GC and the current memory usage is >50% larger than
636 // the estimated live memory usage.
637 return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLive ObjectSizeKb * 3) / 2;
638 #else 640 #else
639 return false; 641 return false;
640 #endif 642 #endif
641 } 643 }
642 644
643 // TODO(haraken): We should improve the GC heuristics.
644 // These heuristics affect performance significantly.
645 bool ThreadState::shouldSchedulePreciseGC() 645 bool ThreadState::shouldSchedulePreciseGC()
646 { 646 {
647 if (gcState() != NoGCScheduled) 647 if (gcState() != NoGCScheduled)
648 return false; 648 return false;
649 #if ENABLE(IDLE_GC) 649 #if ENABLE(IDLE_GC)
650 return false; 650 return false;
651 #else 651 #else
652 // Avoid potential overflow by truncating to Kb. 652 return judgeGCThreshold(1024 * 1024, 1.5);
653 size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
654 // The estimated size is updated when the main thread finishes lazy
655 // sweeping. If this thread reaches here before the main thread finishes
656 // lazy sweeping, the thread will use the estimated size of the last GC.
657 size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
658 // Heap::markedObjectSize() may be underestimated if any thread has not
659 // finished completeSweep().
660 size_t currentObjectSizeKb = currentObjectSize() >> 10;
661 // Schedule a precise GC if Oilpan has allocated more than 1 MB since
662 // the last GC and the current memory usage is >50% larger than
663 // the estimated live memory usage.
664 return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLive ObjectSizeKb * 3) / 2;
665 #endif 653 #endif
666 } 654 }
667 655
668 bool ThreadState::shouldSchedulePageNavigationGC(float estimatedRemovalRatio) 656 bool ThreadState::shouldSchedulePageNavigationGC(float estimatedRemovalRatio)
669 { 657 {
670 if (UNLIKELY(isGCForbidden())) 658 if (UNLIKELY(isGCForbidden()))
671 return false; 659 return false;
672 660
673 if (shouldForceMemoryPressureGC()) 661 if (shouldForceMemoryPressureGC())
674 return true; 662 return true;
675 663
676 // Avoid potential overflow by truncating to Kb. 664 return judgeGCThreshold(1024 * 1024, 1.5);
677 size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10; 665 }
678 // The estimated size is updated when the main thread finishes lazy 666
679 // sweeping. If this thread reaches here before the main thread finishes 667 bool ThreadState::shouldForceConservativeGC()
680 // lazy sweeping, the thread will use the estimated size of the last GC. 668 {
681 size_t estimatedLiveObjectSizeKb = (estimatedLiveObjectSize() >> 10) * (1 - estimatedRemovalRatio); 669 if (UNLIKELY(isGCForbidden()))
682 // Heap::markedObjectSize() may be underestimated if any thread has not 670 return false;
683 // finished completeSweep(). 671
684 size_t currentObjectSizeKb = currentObjectSize() >> 10; 672 if (shouldForceMemoryPressureGC())
685 // Schedule a precise GC if Oilpan has allocated more than 1 MB since 673 return true;
686 // the last GC and the current memory usage is >50% larger than 674
687 // the estimated live memory usage. 675 // TODO(haraken): 400% is too large. Lower the heap growing factor.
688 return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLive ObjectSizeKb * 3) / 2; 676 return judgeGCThreshold(32 * 1024 * 1024, 5.0);
689 } 677 }
690 678
691 void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio) 679 void ThreadState::schedulePageNavigationGCIfNeeded(float estimatedRemovalRatio)
692 { 680 {
693 ASSERT(checkThread()); 681 ASSERT(checkThread());
694 // Finish on-going lazy sweeping. 682 // Finish on-going lazy sweeping.
695 // TODO(haraken): It might not make sense to force completeSweep() for all 683 // TODO(haraken): It might not make sense to force completeSweep() for all
696 // page navigations. 684 // page navigations.
697 completeSweep(); 685 completeSweep();
698 ASSERT(!isSweepingInProgress()); 686 ASSERT(!isSweepingInProgress());
699 ASSERT(!sweepForbidden()); 687 ASSERT(!sweepForbidden());
700 688
701 Heap::reportMemoryUsageForTracing(); 689 Heap::reportMemoryUsageForTracing();
702 if (shouldSchedulePageNavigationGC(estimatedRemovalRatio)) 690 if (shouldSchedulePageNavigationGC(estimatedRemovalRatio))
703 schedulePageNavigationGC(); 691 schedulePageNavigationGC();
704 } 692 }
705 693
706 void ThreadState::schedulePageNavigationGC() 694 void ThreadState::schedulePageNavigationGC()
707 { 695 {
708 ASSERT(checkThread()); 696 ASSERT(checkThread());
709 ASSERT(!isSweepingInProgress()); 697 ASSERT(!isSweepingInProgress());
710 setGCState(PageNavigationGCScheduled); 698 setGCState(PageNavigationGCScheduled);
711 } 699 }
712 700
713 // TODO(haraken): We should improve the GC heuristics.
714 // These heuristics affect performance significantly.
715 bool ThreadState::shouldForceConservativeGC()
716 {
717 if (UNLIKELY(isGCForbidden()))
718 return false;
719
720 if (shouldForceMemoryPressureGC())
721 return true;
722
723 // Avoid potential overflow by truncating to Kb.
724 size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10;
725 // The estimated size is updated when the main thread finishes lazy
726 // sweeping. If this thread reaches here before the main thread finishes
727 // lazy sweeping, the thread will use the estimated size of the last GC.
728 size_t estimatedLiveObjectSizeKb = estimatedLiveObjectSize() >> 10;
729 // Heap::markedObjectSize() may be underestimated if any thread has not
730 // finished completeSweep().
731 size_t currentObjectSizeKb = currentObjectSize() >> 10;
732 // Schedule a conservative GC if Oilpan has allocated more than 32 MB since
733 // the last GC and the current memory usage is >400% larger than
734 // the estimated live memory usage.
735 // TODO(haraken): 400% is too large. Lower the heap growing factor.
736 return allocatedObjectSizeKb >= 32 * 1024 && currentObjectSizeKb > 5 * estim atedLiveObjectSizeKb;
737 }
738
739 void ThreadState::scheduleGCIfNeeded() 701 void ThreadState::scheduleGCIfNeeded()
740 { 702 {
741 ASSERT(checkThread()); 703 ASSERT(checkThread());
742 // Allocation is allowed during sweeping, but those allocations should not 704 // Allocation is allowed during sweeping, but those allocations should not
743 // trigger nested GCs. 705 // trigger nested GCs.
744 if (isSweepingInProgress()) 706 if (isSweepingInProgress())
745 return; 707 return;
746 ASSERT(!sweepForbidden()); 708 ASSERT(!sweepForbidden());
747 709
748 Heap::reportMemoryUsageForTracing(); 710 Heap::reportMemoryUsageForTracing();
(...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after
1632 json->beginArray(it->key.ascii().data()); 1594 json->beginArray(it->key.ascii().data());
1633 for (size_t age = 0; age <= maxHeapObjectAge; ++age) 1595 for (size_t age = 0; age <= maxHeapObjectAge; ++age)
1634 json->pushInteger(it->value.ages[age]); 1596 json->pushInteger(it->value.ages[age]);
1635 json->endArray(); 1597 json->endArray();
1636 } 1598 }
1637 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release()); 1599 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release());
1638 } 1600 }
1639 #endif 1601 #endif
1640 1602
1641 } // namespace blink 1603 } // namespace blink
OLDNEW
« no previous file with comments | « Source/platform/heap/ThreadState.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698