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 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 |