Changeset 192721 in webkit


Ignore:
Timestamp:
Nov 20, 2015 8:40:40 PM (8 years ago)
Author:
akling@apple.com
Message:

GC timers should carry on gracefully when Heap claims it grew from GC.
<https://webkit.org/b/151521>

Reviewed by Mark Lam.

TL;DR the Heap "extra memory" reporting APIs are hard to use 100% correctly
and GC scheduling shouldn't break if someone makes a mistake with it.

The JSC::Heap allows you to report an extra memory cost for any GC object.
This is reported first when allocating the memory, and then each time the
object is visited during the marking phase.

When reporting an allocation, it's added to the Heap's "bytes allocated in
this cycle" counter. This contributes to the computed heap size at the start
of a collection.

When visiting a GC object that reports extra memory, it's added to the Heap's
"extra memory visited in this collection" counter. This contributes to the
computed heap size at the end of a collection.

As you can see, this means that visiting more memory than we said we allocated
can lead to the Heap thinking it's bigger after a collection than it was before.

Clients of this API do some sketchy things to compute costs, for instance
StringImpl cost is determined by dividing the number of bytes used for the
characters, and dividing it by the StringImpl's ref count. Since a JSString
could be backed by any StringImpl, any code that modifies a StringImpl's
ref count during collection will change the extra memory reported by all
JSString objects that wrap that StringImpl.

So anyways...

The object death rate, which is the basis for when to schedule the next
collection is computed like so:

deathRate = (sizeBeforeGC - sizeAfterGC) / sizeBeforeGC

This patch adds a safety mechanism that returns a zero death rate when the Heap
claims it grew from collection.

  • heap/EdenGCActivityCallback.cpp:

(JSC::EdenGCActivityCallback::deathRate):

  • heap/FullGCActivityCallback.cpp:

(JSC::FullGCActivityCallback::deathRate):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r192708 r192721  
     12015-11-20  Andreas Kling  <akling@apple.com>
     2
     3        GC timers should carry on gracefully when Heap claims it grew from GC.
     4        <https://webkit.org/b/151521>
     5
     6        Reviewed by Mark Lam.
     7
     8        TL;DR the Heap "extra memory" reporting APIs are hard to use 100% correctly
     9        and GC scheduling shouldn't break if someone makes a mistake with it.
     10
     11        The JSC::Heap allows you to report an extra memory cost for any GC object.
     12        This is reported first when allocating the memory, and then each time the
     13        object is visited during the marking phase.
     14
     15        When reporting an allocation, it's added to the Heap's "bytes allocated in
     16        this cycle" counter. This contributes to the computed heap size at the start
     17        of a collection.
     18
     19        When visiting a GC object that reports extra memory, it's added to the Heap's
     20        "extra memory visited in this collection" counter. This contributes to the
     21        computed heap size at the end of a collection.
     22
     23        As you can see, this means that visiting more memory than we said we allocated
     24        can lead to the Heap thinking it's bigger after a collection than it was before.
     25
     26        Clients of this API do some sketchy things to compute costs, for instance
     27        StringImpl cost is determined by dividing the number of bytes used for the
     28        characters, and dividing it by the StringImpl's ref count. Since a JSString
     29        could be backed by any StringImpl, any code that modifies a StringImpl's
     30        ref count during collection will change the extra memory reported by all
     31        JSString objects that wrap that StringImpl.
     32
     33        So anyways...
     34
     35        The object death rate, which is the basis for when to schedule the next
     36        collection is computed like so:
     37
     38            deathRate = (sizeBeforeGC - sizeAfterGC) / sizeBeforeGC
     39
     40        This patch adds a safety mechanism that returns a zero death rate when the Heap
     41        claims it grew from collection.
     42
     43        * heap/EdenGCActivityCallback.cpp:
     44        (JSC::EdenGCActivityCallback::deathRate):
     45        * heap/FullGCActivityCallback.cpp:
     46        (JSC::FullGCActivityCallback::deathRate):
     47
    1482015-11-20  Mark Lam  <mark.lam@apple.com>
    249
  • trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp

    r165940 r192721  
    5555    if (!sizeBefore)
    5656        return 1.0;
     57    if (sizeAfter > sizeBefore) {
     58        // GC caused the heap to grow(!)
     59        // This could happen if the we visited more extra memory than was reported allocated.
     60        // We don't return a negative death rate, since that would schedule the next GC in the past.
     61        return 0;
     62    }
    5763    return static_cast<double>(sizeBefore - sizeAfter) / static_cast<double>(sizeBefore);
    5864}
  • trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp

    r185387 r192721  
    7171    if (!sizeBefore)
    7272        return 1.0;
     73    if (sizeAfter > sizeBefore) {
     74        // GC caused the heap to grow(!)
     75        // This could happen if the we visited more extra memory than was reported allocated.
     76        // We don't return a negative death rate, since that would schedule the next GC in the past.
     77        return 0;
     78    }
    7379    return static_cast<double>(sizeBefore - sizeAfter) / static_cast<double>(sizeBefore);
    7480}
Note: See TracChangeset for help on using the changeset viewer.