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 24 matching lines...) Expand all Loading... | |
| 35 #include "platform/TraceEvent.h" | 35 #include "platform/TraceEvent.h" |
| 36 #include "platform/heap/AddressSanitizer.h" | 36 #include "platform/heap/AddressSanitizer.h" |
| 37 #include "platform/heap/CallbackStack.h" | 37 #include "platform/heap/CallbackStack.h" |
| 38 #include "platform/heap/Handle.h" | 38 #include "platform/heap/Handle.h" |
| 39 #include "platform/heap/Heap.h" | 39 #include "platform/heap/Heap.h" |
| 40 #include "platform/heap/SafePoint.h" | 40 #include "platform/heap/SafePoint.h" |
| 41 #include "platform/scheduler/Scheduler.h" | 41 #include "platform/scheduler/Scheduler.h" |
| 42 #include "public/platform/Platform.h" | 42 #include "public/platform/Platform.h" |
| 43 #include "public/platform/WebThread.h" | 43 #include "public/platform/WebThread.h" |
| 44 #include "public/platform/WebTraceLocation.h" | 44 #include "public/platform/WebTraceLocation.h" |
| 45 #include "wtf/Partitions.h" | |
| 45 #include "wtf/ThreadingPrimitives.h" | 46 #include "wtf/ThreadingPrimitives.h" |
| 46 #if ENABLE(GC_PROFILING) | 47 #if ENABLE(GC_PROFILING) |
| 47 #include "platform/TracedValue.h" | 48 #include "platform/TracedValue.h" |
| 48 #include "wtf/text/StringHash.h" | 49 #include "wtf/text/StringHash.h" |
| 49 #endif | 50 #endif |
| 50 | 51 |
| 51 #if OS(WIN) | 52 #if OS(WIN) |
| 52 #include <stddef.h> | 53 #include <stddef.h> |
| 53 #include <windows.h> | 54 #include <windows.h> |
| 54 #include <winnt.h> | 55 #include <winnt.h> |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 493 AtomicallyInitializedStaticReference(PersistentNode, anchor, new PersistentA nchor); | 494 AtomicallyInitializedStaticReference(PersistentNode, anchor, new PersistentA nchor); |
| 494 return anchor; | 495 return anchor; |
| 495 } | 496 } |
| 496 | 497 |
| 497 Mutex& ThreadState::globalRootsMutex() | 498 Mutex& ThreadState::globalRootsMutex() |
| 498 { | 499 { |
| 499 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex); | 500 AtomicallyInitializedStaticReference(Mutex, mutex, new Mutex); |
| 500 return mutex; | 501 return mutex; |
| 501 } | 502 } |
| 502 | 503 |
| 503 // FIXME: We should improve the GC heuristics. | 504 // TODO(haraken): We should improve the GC heuristics. |
| 504 // These heuristics affect performance significantly. | 505 // These heuristics affect performance significantly. |
| 505 bool ThreadState::shouldScheduleIdleGC() | 506 bool ThreadState::shouldScheduleIdleGC() |
| 506 { | 507 { |
| 507 if (gcState() != NoGCScheduled) | 508 if (gcState() != NoGCScheduled) |
| 508 return false; | 509 return false; |
| 509 #if ENABLE(OILPAN) | 510 #if ENABLE(OILPAN) |
| 510 // The estimated size is updated when the main thread finishes lazy | 511 // The estimated size is updated when the main thread finishes lazy |
| 511 // sweeping. If this thread reaches here before the main thread finishes | 512 // sweeping. If this thread reaches here before the main thread finishes |
| 512 // lazy sweeping, the thread will use the estimated size of the last GC. | 513 // lazy sweeping, the thread will use the estimated size of the last GC. |
| 513 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); | 514 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); |
| 514 // Schedule an idle GC if more than 512 KB has been allocated since | |
| 515 // the last GC and the current memory usage (=allocated + estimated) | |
| 516 // is >50% larger than the estimated live memory usage. | |
| 517 size_t allocatedObjectSize = Heap::allocatedObjectSize(); | 515 size_t allocatedObjectSize = Heap::allocatedObjectSize(); |
| 518 return allocatedObjectSize >= 512 * 1024 && allocatedObjectSize > estimatedL iveObjectSize / 2; | 516 // Heap::markedObjectSize() may be underestimated if any thread has not |
| 517 // finished completeSweep(). | |
| 518 size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); | |
| 519 // Schedule an idle GC if the current memory usage is >1MB | |
| 520 // and is >50% larger than the estimated live memory usage. | |
| 521 return currentObjectSize >= 1024 * 1024 && currentObjectSize > estimatedLive ObjectSize * 3 / 2; | |
|
sof
2015/04/23 15:20:33
Re: (currentObjectSize >= 1024 * 1024) -- wouldn't
| |
| 519 #else | 522 #else |
| 520 return false; | 523 return false; |
| 521 #endif | 524 #endif |
| 522 } | 525 } |
| 523 | 526 |
| 524 // FIXME: We should improve the GC heuristics. | 527 // TODO(haraken): We should improve the GC heuristics. |
| 525 // These heuristics affect performance significantly. | 528 // These heuristics affect performance significantly. |
| 526 bool ThreadState::shouldSchedulePreciseGC() | 529 bool ThreadState::shouldSchedulePreciseGC() |
| 527 { | 530 { |
| 528 if (gcState() != NoGCScheduled) | 531 if (gcState() != NoGCScheduled) |
| 529 return false; | 532 return false; |
| 530 #if ENABLE(OILPAN) | 533 #if ENABLE(OILPAN) |
| 531 return false; | 534 return false; |
| 532 #else | 535 #else |
| 533 // The estimated size is updated when the main thread finishes lazy | 536 // The estimated size is updated when the main thread finishes lazy |
| 534 // sweeping. If this thread reaches here before the main thread finishes | 537 // sweeping. If this thread reaches here before the main thread finishes |
| 535 // lazy sweeping, the thread will use the estimated size of the last GC. | 538 // lazy sweeping, the thread will use the estimated size of the last GC. |
| 536 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); | 539 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); |
| 537 // Schedule a precise GC if more than 512 KB has been allocated since | |
| 538 // the last GC and the current memory usage (=allocated + estimated) | |
| 539 // is >50% larger than the estimated live memory usage. | |
| 540 size_t allocatedObjectSize = Heap::allocatedObjectSize(); | 540 size_t allocatedObjectSize = Heap::allocatedObjectSize(); |
| 541 return allocatedObjectSize >= 512 * 1024 && allocatedObjectSize > estimatedL iveObjectSize / 2; | 541 // Heap::markedObjectSize() may be underestimated if any thread has not |
| 542 // finished completeSweep(). | |
| 543 size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); | |
| 544 // Schedule a precise GC if the current memory usage is >1MB | |
| 545 // and is >50% larger than the estimated live memory usage. | |
| 546 return currentObjectSize >= 1024 * 1024 && currentObjectSize > estimatedLive ObjectSize * 3 / 2; | |
| 542 #endif | 547 #endif |
| 543 } | 548 } |
| 544 | 549 |
| 545 // FIXME: We should improve the GC heuristics. | 550 // TODO(haraken): We should improve the GC heuristics. |
| 546 // These heuristics affect performance significantly. | 551 // These heuristics affect performance significantly. |
| 547 bool ThreadState::shouldForceConservativeGC() | 552 bool ThreadState::shouldForceConservativeGC() |
| 548 { | 553 { |
| 549 if (UNLIKELY(m_gcForbiddenCount)) | 554 if (UNLIKELY(m_gcForbiddenCount)) |
| 550 return false; | 555 return false; |
| 551 | 556 |
| 552 if (Heap::isUrgentGCRequested()) | |
| 553 return true; | |
| 554 | |
| 555 // The estimated size is updated when the main thread finishes lazy | 557 // The estimated size is updated when the main thread finishes lazy |
| 556 // sweeping. If this thread reaches here before the main thread finishes | 558 // sweeping. If this thread reaches here before the main thread finishes |
| 557 // lazy sweeping, the thread will use the estimated size of the last GC. | 559 // lazy sweeping, the thread will use the estimated size of the last GC. |
| 558 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); | 560 size_t estimatedLiveObjectSize = Heap::estimatedLiveObjectSize(); |
| 559 size_t allocatedObjectSize = Heap::allocatedObjectSize(); | 561 size_t allocatedObjectSize = Heap::allocatedObjectSize(); |
| 560 if (Heap::markedObjectSize() + allocatedObjectSize >= 300 * 1024 * 1024) { | 562 // Heap::markedObjectSize() may be underestimated if any thread has not |
| 563 // finished completeSweep(). | |
| 564 size_t currentObjectSize = allocatedObjectSize + Heap::markedObjectSize() + WTF::Partitions::totalSizeOfCommittedPages(); | |
| 565 if (currentObjectSize >= 300 * 1024 * 1024) { | |
| 561 // If we're consuming too much memory, trigger a conservative GC | 566 // If we're consuming too much memory, trigger a conservative GC |
| 562 // aggressively. This is a safe guard to avoid OOM. | 567 // aggressively. This is a safe guard to avoid OOM. |
| 563 return allocatedObjectSize > estimatedLiveObjectSize / 2; | 568 return currentObjectSize > estimatedLiveObjectSize * 3 / 2; |
| 564 } | 569 } |
| 565 // Schedule a conservative GC if more than 32 MB has been allocated since | 570 // Schedule a conservative GC if the current memory usage is >32MB |
| 566 // the last GC and the current memory usage (=allocated + estimated) | 571 // and is >400% larger than the estimated live memory usage. |
| 567 // is >500% larger than the estimated live memory usage. | 572 // TODO(haraken): 400% is too large. Lower the heap growing factor. |
| 568 return allocatedObjectSize >= 32 * 1024 * 1024 && allocatedObjectSize > 4 * estimatedLiveObjectSize; | 573 return currentObjectSize >= 32 * 1024 * 1024 && currentObjectSize > 5 * esti matedLiveObjectSize; |
| 569 } | 574 } |
| 570 | 575 |
| 571 void ThreadState::scheduleGCIfNeeded() | 576 void ThreadState::scheduleGCIfNeeded() |
| 572 { | 577 { |
| 573 checkThread(); | 578 checkThread(); |
| 574 // Allocation is allowed during sweeping, but those allocations should not | 579 // Allocation is allowed during sweeping, but those allocations should not |
| 575 // trigger nested GCs. Does not apply if an urgent GC has been requested. | 580 // trigger nested GCs. |
| 576 if (isSweepingInProgress() && UNLIKELY(!Heap::isUrgentGCRequested())) | 581 if (isSweepingInProgress()) |
| 577 return; | 582 return; |
| 578 ASSERT(!sweepForbidden()); | 583 ASSERT(!sweepForbidden()); |
| 579 | 584 |
| 580 if (shouldForceConservativeGC()) { | 585 if (shouldForceConservativeGC()) { |
| 581 if (Heap::isUrgentGCRequested()) { | 586 Heap::collectGarbage(HeapPointersOnStack, GCWithoutSweep, Heap::Conserva tiveGC); |
| 582 // If GC is deemed urgent, eagerly sweep and finalize any external a llocations right away. | |
| 583 Heap::collectGarbage(HeapPointersOnStack, GCWithSweep, Heap::Conserv ativeGC); | |
| 584 } else { | |
| 585 // Otherwise, schedule a lazy sweeping in an idle task. | |
| 586 Heap::collectGarbage(HeapPointersOnStack, GCWithoutSweep, Heap::Cons ervativeGC); | |
| 587 } | |
| 588 return; | 587 return; |
| 589 } | 588 } |
| 590 if (shouldSchedulePreciseGC()) | 589 if (shouldSchedulePreciseGC()) |
| 591 schedulePreciseGC(); | 590 schedulePreciseGC(); |
| 592 else if (shouldScheduleIdleGC()) | 591 else if (shouldScheduleIdleGC()) |
| 593 scheduleIdleGC(); | 592 scheduleIdleGC(); |
| 594 } | 593 } |
| 595 | 594 |
| 596 void ThreadState::performIdleGC(double deadlineSeconds) | 595 void ThreadState::performIdleGC(double deadlineSeconds) |
| 597 { | 596 { |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 839 | 838 |
| 840 if (isMainThread()) | 839 if (isMainThread()) |
| 841 ScriptForbiddenScope::exit(); | 840 ScriptForbiddenScope::exit(); |
| 842 } | 841 } |
| 843 | 842 |
| 844 postSweep(); | 843 postSweep(); |
| 845 } | 844 } |
| 846 | 845 |
| 847 void ThreadState::postSweep() | 846 void ThreadState::postSweep() |
| 848 { | 847 { |
| 849 if (isMainThread()) | 848 if (isMainThread()) { |
| 850 Heap::setEstimatedLiveObjectSize(Heap::markedObjectSize()); | 849 // At the point where the main thread finishes lazy sweeping, |
| 850 // we estimate the live object size. Heap::markedObjectSize() | |
| 851 // may be underestimated if any other thread has not finished | |
| 852 // lazy sweeping. | |
| 853 Heap::setEstimatedLiveObjectSize(Heap::markedObjectSize() + Heap::extern alObjectSizeAtLastGC()); | |
| 854 } | |
| 851 | 855 |
| 852 switch (gcState()) { | 856 switch (gcState()) { |
| 853 case Sweeping: | 857 case Sweeping: |
| 854 setGCState(NoGCScheduled); | 858 setGCState(NoGCScheduled); |
| 855 break; | 859 break; |
| 856 case SweepingAndPreciseGCScheduled: | 860 case SweepingAndPreciseGCScheduled: |
| 857 setGCState(PreciseGCScheduled); | 861 setGCState(PreciseGCScheduled); |
| 858 break; | 862 break; |
| 859 case SweepingAndIdleGCScheduled: | 863 case SweepingAndIdleGCScheduled: |
| 860 setGCState(NoGCScheduled); | 864 setGCState(NoGCScheduled); |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1292 json->beginArray(it->key.ascii().data()); | 1296 json->beginArray(it->key.ascii().data()); |
| 1293 for (size_t age = 0; age <= maxHeapObjectAge; ++age) | 1297 for (size_t age = 0; age <= maxHeapObjectAge; ++age) |
| 1294 json->pushInteger(it->value.ages[age]); | 1298 json->pushInteger(it->value.ages[age]); |
| 1295 json->endArray(); | 1299 json->endArray(); |
| 1296 } | 1300 } |
| 1297 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release()); | 1301 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(TRACE_DISABLED_BY_DEFAULT("blink_gc"), s tatsName, this, json.release()); |
| 1298 } | 1302 } |
| 1299 #endif | 1303 #endif |
| 1300 | 1304 |
| 1301 } // namespace blink | 1305 } // namespace blink |
| OLD | NEW |