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 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
522 AtomicallyInitializedStaticReference(PersistentAnchor, anchor, new Persisten tAnchor); | 522 AtomicallyInitializedStaticReference(PersistentAnchor, anchor, new Persisten tAnchor); |
523 return anchor; | 523 return anchor; |
524 } | 524 } |
525 | 525 |
526 Mutex& ThreadState::globalRootsMutex() | 526 Mutex& ThreadState::globalRootsMutex() |
527 { | 527 { |
528 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex); | 528 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex); |
529 return mutex; | 529 return mutex; |
530 } | 530 } |
531 | 531 |
532 bool ThreadState::shouldForceMemoryPressureGC() | |
533 { | |
534 // Avoid potential overflow by truncating to Kb. | |
535 size_t currentObjectSizeKb = (Heap::allocatedObjectSize() + Heap::markedObje ctSize() + WTF::Partitions::totalSizeOfCommittedPages()) >> 10; | |
536 if (currentObjectSizeKb < 300 * 1024) | |
537 return false; | |
538 | |
539 size_t estimatedLiveObjectSizeKb = Heap::estimatedLiveObjectSize() >> 10; | |
540 // If we're consuming too much memory, trigger a conservative GC | |
541 // aggressively. This is a safe guard to avoid OOM. | |
542 return currentObjectSizeKb > (estimatedLiveObjectSizeKb * 3) / 2; | |
543 } | |
544 | |
532 // TODO(haraken): We should improve the GC heuristics. | 545 // TODO(haraken): We should improve the GC heuristics. |
533 // These heuristics affect performance significantly. | 546 // These heuristics affect performance significantly. |
534 bool ThreadState::shouldScheduleIdleGC() | 547 bool ThreadState::shouldScheduleIdleGC() |
535 { | 548 { |
536 if (gcState() != NoGCScheduled) | 549 if (gcState() != NoGCScheduled) |
537 return false; | 550 return false; |
538 #if ENABLE(IDLE_GC) | 551 #if ENABLE(IDLE_GC) |
552 // Avoid potential overflow by truncating to Kb. | |
553 size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10; | |
539 // The estimated size is updated when the main thread finishes lazy | 554 // The estimated size is updated when the main thread finishes lazy |
540 // sweeping. If this thread reaches here before the main thread finishes | 555 // sweeping. If this thread reaches here before the main thread finishes |
541 // lazy sweeping, the thread will use the estimated size of the last GC. | 556 // lazy sweeping, the thread will use the estimated size of the last GC. |
542 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); | 557 size_t estimatedLiveObjectSizeKb = Heap::estimatedLiveObjectSize() >> 10; |
543 size_t allocatedObjectSize = Heap::allocatedObjectSize(); | |
544 // Heap::markedObjectSize() may be underestimated if any thread has not | 558 // Heap::markedObjectSize() may be underestimated if any thread has not |
545 // finished completeSweep(). | 559 // finished completeSweep(). |
546 size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); | 560 size_t currentObjectSizeKb = allocatedObjectSizeKb + ((Heap::markedObjectSiz e() + WTF::Partitions::totalSizeOfCommittedPages()) >> 10); |
547 // Schedule an idle GC if Oilpan has allocated more than 1 MB since | 561 // Schedule an idle GC if Oilpan has allocated more than 1 MB since |
548 // the last GC and the current memory usage is >50% larger than | 562 // the last GC and the current memory usage is >50% larger than |
549 // the estimated live memory usage. | 563 // the estimated live memory usage. |
550 return allocatedObjectSize >= 1024 * 1024 && currentObjectSize > estimatedLi veObjectSize * 3 / 2; | 564 return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLive ObjectSizeKb * 3) / 2; |
551 #else | 565 #else |
552 return false; | 566 return false; |
553 #endif | 567 #endif |
554 } | 568 } |
555 | 569 |
556 // TODO(haraken): We should improve the GC heuristics. | 570 // TODO(haraken): We should improve the GC heuristics. |
557 // These heuristics affect performance significantly. | 571 // These heuristics affect performance significantly. |
558 bool ThreadState::shouldSchedulePreciseGC() | 572 bool ThreadState::shouldSchedulePreciseGC() |
559 { | 573 { |
560 if (gcState() != NoGCScheduled) | 574 if (gcState() != NoGCScheduled) |
561 return false; | 575 return false; |
562 #if ENABLE(IDLE_GC) | 576 #if ENABLE(IDLE_GC) |
563 return false; | 577 return false; |
564 #else | 578 #else |
579 // Avoid potential overflow by truncating to Kb. | |
580 size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10; | |
565 // The estimated size is updated when the main thread finishes lazy | 581 // The estimated size is updated when the main thread finishes lazy |
566 // sweeping. If this thread reaches here before the main thread finishes | 582 // sweeping. If this thread reaches here before the main thread finishes |
567 // lazy sweeping, the thread will use the estimated size of the last GC. | 583 // lazy sweeping, the thread will use the estimated size of the last GC. |
568 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); | 584 size_t estimatedLiveObjectSizeKb = Heap::estimatedLiveObjectSize() >> 10; |
569 size_t allocatedObjectSize = Heap::allocatedObjectSize(); | |
570 // Heap::markedObjectSize() may be underestimated if any thread has not | 585 // Heap::markedObjectSize() may be underestimated if any thread has not |
571 // finished completeSweep(). | 586 // finished completeSweep(). |
572 size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); | 587 size_t currentObjectSizeKb = allocatedObjectSizeKb + ((Heap::markedObjectSiz e() + WTF::Partitions::totalSizeOfCommittedPages()) >> 10); |
573 // Schedule a precise GC if Oilpan has allocated more than 1 MB since | 588 // Schedule a precise GC if Oilpan has allocated more than 1 MB since |
574 // the last GC and the current memory usage is >50% larger than | 589 // the last GC and the current memory usage is >50% larger than |
575 // the estimated live memory usage. | 590 // the estimated live memory usage. |
576 return allocatedObjectSize >= 1024 * 1024 && currentObjectSize > estimatedLi veObjectSize * 3 / 2; | 591 return allocatedObjectSizeKb >= 1024 && currentObjectSizeKb > (estimatedLive ObjectSizeKb * 3) / 2; |
577 #endif | 592 #endif |
578 } | 593 } |
579 | 594 |
580 // TODO(haraken): We should improve the GC heuristics. | 595 // TODO(haraken): We should improve the GC heuristics. |
581 // These heuristics affect performance significantly. | 596 // These heuristics affect performance significantly. |
582 bool ThreadState::shouldForceConservativeGC() | 597 bool ThreadState::shouldForceConservativeGC() |
583 { | 598 { |
584 if (UNLIKELY(isGCForbidden())) | 599 if (UNLIKELY(isGCForbidden())) |
585 return false; | 600 return false; |
586 | 601 |
602 if (shouldForceMemoryPressureGC()) | |
603 return true; | |
604 | |
605 // Avoid potential overflow by truncating to Kb. | |
606 size_t allocatedObjectSizeKb = Heap::allocatedObjectSize() >> 10; | |
587 // The estimated size is updated when the main thread finishes lazy | 607 // The estimated size is updated when the main thread finishes lazy |
588 // sweeping. If this thread reaches here before the main thread finishes | 608 // sweeping. If this thread reaches here before the main thread finishes |
589 // lazy sweeping, the thread will use the estimated size of the last GC. | 609 // lazy sweeping, the thread will use the estimated size of the last GC. |
590 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); | 610 size_t estimatedLiveObjectSizeKb = Heap::estimatedLiveObjectSize() >> 10; |
591 size_t allocatedObjectSize = Heap::allocatedObjectSize(); | |
592 // Heap::markedObjectSize() may be underestimated if any thread has not | 611 // Heap::markedObjectSize() may be underestimated if any thread has not |
593 // finished completeSweep(). | 612 // finished completeSweep(). |
594 size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); | 613 size_t currentObjectSizeKb = allocatedObjectSizeKb + ((Heap::markedObjectSiz e() + WTF::Partitions::totalSizeOfCommittedPages()) >> 10); |
595 if (currentObjectSize >= 300 * 1024 * 1024) { | |
596 // If we're consuming too much memory, trigger a conservative GC | |
597 // aggressively. This is a safe guard to avoid OOM. | |
598 return currentObjectSize > estimatedLiveObjectSize * 3 / 2; | |
599 } | |
600 // Schedule a conservative GC if Oilpan has allocated more than 32 MB since | 614 // Schedule a conservative GC if Oilpan has allocated more than 32 MB since |
601 // the last GC and the current memory usage is >400% larger than | 615 // the last GC and the current memory usage is >400% larger than |
602 // the estimated live memory usage. | 616 // the estimated live memory usage. |
603 // TODO(haraken): 400% is too large. Lower the heap growing factor. | 617 // TODO(haraken): 400% is too large. Lower the heap growing factor. |
604 return allocatedObjectSize >= 32 * 1024 * 1024 && currentObjectSize > 5 * es timatedLiveObjectSize; | 618 return allocatedObjectSizeKb >= 32 * 1024 && currentObjectSizeKb > 5 * estim atedLiveObjectSizeKb; |
605 } | 619 } |
606 | 620 |
607 void ThreadState::scheduleGCIfNeeded() | 621 void ThreadState::scheduleGCIfNeeded() |
608 { | 622 { |
609 checkThread(); | 623 checkThread(); |
610 // Allocation is allowed during sweeping, but those allocations should not | 624 // Allocation is allowed during sweeping, but those allocations should not |
611 // trigger nested GCs. | 625 // trigger nested GCs. |
612 if (isSweepingInProgress()) | 626 if (isSweepingInProgress()) |
613 return; | 627 return; |
614 ASSERT(!sweepForbidden()); | 628 ASSERT(!sweepForbidden()); |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
795 m_gcState = gcState; | 809 m_gcState = gcState; |
796 } | 810 } |
797 | 811 |
798 #undef VERIFY_STATE_TRANSITION | 812 #undef VERIFY_STATE_TRANSITION |
799 | 813 |
800 ThreadState::GCState ThreadState::gcState() const | 814 ThreadState::GCState ThreadState::gcState() const |
801 { | 815 { |
802 return m_gcState; | 816 return m_gcState; |
803 } | 817 } |
804 | 818 |
805 void ThreadState::didV8GC() | 819 void ThreadState::didV8MajorGC() |
806 { | 820 { |
807 checkThread(); | 821 checkThread(); |
808 if (isMainThread()) { | 822 if (isMainThread()) { |
809 // Lower the estimated live object size because the V8 major GC is | 823 // Lower the estimated live object size because the V8 major GC is |
810 // expected to have collected a lot of DOM wrappers and dropped | 824 // expected to have collected a lot of DOM wrappers and dropped |
811 // references to their DOM objects. | 825 // references to their DOM objects. |
812 Heap::setEstimatedLiveObjectSize(Heap::estimatedLiveObjectSize() / 2); | 826 Heap::setEstimatedLiveObjectSize(Heap::estimatedLiveObjectSize() / 2); |
827 | |
828 #if 0 | |
829 if (shouldForceMemoryPressureGC()) { | |
830 // Under memory pressure, force a conservative GC. | |
831 Heap::collectGarbage(HeapPointersOnStack, GCWithoutSweep, Heap::Cons ervativeGC); | |
832 return; | |
833 } | |
haraken
2015/06/16 16:21:27
Actually I don't fully understand an issue of call
sof
2015/06/16 16:27:31
Oops, #if 0 - will undo that, ofc.
It triggering
haraken
2015/06/16 16:36:44
I'm OK with landing this CL, but that sounds like
| |
834 #endif | |
813 } | 835 } |
814 } | 836 } |
815 | 837 |
816 void ThreadState::runScheduledGC(StackState stackState) | 838 void ThreadState::runScheduledGC(StackState stackState) |
817 { | 839 { |
818 checkThread(); | 840 checkThread(); |
819 if (stackState != NoHeapPointersOnStack) | 841 if (stackState != NoHeapPointersOnStack) |
820 return; | 842 return; |
821 | 843 |
822 // If a safe point is entered while initiating a GC, we clearly do | 844 // If a safe point is entered while initiating a GC, we clearly do |
(...skipping 604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1427 json->beginArray(it->key.ascii().data()); | 1449 json->beginArray(it->key.ascii().data()); |
1428 for (size_t age = 0; age <= maxHeapObjectAge; ++age) | 1450 for (size_t age = 0; age <= maxHeapObjectAge; ++age) |
1429 json->pushInteger(it->value.ages[age]); | 1451 json->pushInteger(it->value.ages[age]); |
1430 json->endArray(); | 1452 json->endArray(); |
1431 } | 1453 } |
1432 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release()); | 1454 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release()); |
1433 } | 1455 } |
1434 #endif | 1456 #endif |
1435 | 1457 |
1436 } // namespace blink | 1458 } // namespace blink |
OLD | NEW |