⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 181821 in webkit


Ignore:
Timestamp:
Mar 20, 2015, 7:02:44 PM (11 years ago)
Author:
mhahnenb@gmail.com
Message:

GCTimer should know keep track of nested GC phases
https://bugs.webkit.org/show_bug.cgi?id=142675

Reviewed by Darin Adler.

Source/JavaScriptCore:

This improves the GC phase timing output in Heap.cpp by linking
phases nested inside other phases together, allowing tools
to compute how much time we're spending in various nested phases.

  • heap/Heap.cpp:

Tools:

Adds a tool to aid in parsing the GC phase timing output into a
tree-like structure based on the parent-child relationships
of nested GC phases.

  • Scripts/parse-gc-phase-timings: Added.

(Timing):
(Timing.init):
(Timing.unicode):
(Timing.str):
(Timing.repr):
(parse_input):
(print_timing_node):
(print_timing_tree):
(link_parents):
(main):

Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r181818 r181821  
     12015-03-20  Mark Hahnenberg  <mhahnenb@gmail.com>
     2
     3        GCTimer should know keep track of nested GC phases
     4        https://bugs.webkit.org/show_bug.cgi?id=142675
     5
     6        Reviewed by Darin Adler.
     7
     8        This improves the GC phase timing output in Heap.cpp by linking
     9        phases nested inside other phases together, allowing tools
     10        to compute how much time we're spending in various nested phases.
     11
     12        * heap/Heap.cpp:
     13
    1142015-03-20  Geoffrey Garen  <ggaren@apple.com>
    215
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r181486 r181821  
    8181struct GCTimer {
    8282    GCTimer(const char* name)
    83         : m_name(name)
     83        : name(name)
    8484    {
    8585    }
    8686    ~GCTimer()
    8787    {
    88         logData(m_allCollectionData, "(All)");
    89         logData(m_edenCollectionData, "(Eden)");
    90         logData(m_fullCollectionData, "(Full)");
     88        logData(allCollectionData, "(All)");
     89        logData(edenCollectionData, "(Eden)");
     90        logData(fullCollectionData, "(Full)");
    9191    }
    9292
    9393    struct TimeRecord {
    9494        TimeRecord()
    95             : m_time(0)
    96             , m_min(std::numeric_limits<double>::infinity())
    97             , m_max(0)
    98             , m_count(0)
     95            : time(0)
     96            , min(std::numeric_limits<double>::infinity())
     97            , max(0)
     98            , count(0)
    9999        {
    100100        }
    101101
    102         double m_time;
    103         double m_min;
    104         double m_max;
    105         size_t m_count;
     102        double time;
     103        double min;
     104        double max;
     105        size_t count;
    106106    };
    107107
    108108    void logData(const TimeRecord& data, const char* extra)
    109109    {
    110         dataLogF("[%d] %s %s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf, count %lu)\n",
     110        dataLogF("[%d] %s (Parent: %s) %s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf, count %lu)\n",
    111111            getCurrentProcessID(),
    112             m_name, extra,
    113             data.m_time * 1000,
    114             data.m_time * 1000 / data.m_count,
    115             data.m_min * 1000,
    116             data.m_max * 1000,
    117             data.m_count);
     112            name,
     113            parent ? parent->name : "nullptr",
     114            extra,
     115            data.time * 1000,
     116            data.time * 1000 / data.count,
     117            data.min * 1000,
     118            data.max * 1000,
     119            data.count);
    118120    }
    119121
    120122    void updateData(TimeRecord& data, double duration)
    121123    {
    122         if (duration < data.m_min)
    123             data.m_min = duration;
    124         if (duration > data.m_max)
    125             data.m_max = duration;
    126         data.m_count++;
    127         data.m_time += duration;
     124        if (duration < data.min)
     125            data.min = duration;
     126        if (duration > data.max)
     127            data.max = duration;
     128        data.count++;
     129        data.time += duration;
    128130    }
    129131
    130132    void didFinishPhase(HeapOperation collectionType, double duration)
    131133    {
    132         TimeRecord& data = collectionType == EdenCollection ? m_edenCollectionData : m_fullCollectionData;
     134        TimeRecord& data = collectionType == EdenCollection ? edenCollectionData : fullCollectionData;
    133135        updateData(data, duration);
    134         updateData(m_allCollectionData, duration);
    135     }
    136 
    137     TimeRecord m_allCollectionData;
    138     TimeRecord m_fullCollectionData;
    139     TimeRecord m_edenCollectionData;
    140     const char* m_name;
     136        updateData(allCollectionData, duration);
     137    }
     138
     139    static GCTimer* s_currentGlobalTimer;
     140
     141    TimeRecord allCollectionData;
     142    TimeRecord fullCollectionData;
     143    TimeRecord edenCollectionData;
     144    const char* name;
     145    GCTimer* parent { nullptr };
    141146};
    142147
     148GCTimer* GCTimer::s_currentGlobalTimer = nullptr;
     149
    143150struct GCTimerScope {
    144     GCTimerScope(GCTimer* timer, HeapOperation collectionType)
    145         : m_timer(timer)
    146         , m_start(WTF::monotonicallyIncreasingTime())
    147         , m_collectionType(collectionType)
     151    GCTimerScope(GCTimer& timer, HeapOperation collectionType)
     152        : timer(timer)
     153        , start(WTF::monotonicallyIncreasingTime())
     154        , collectionType(collectionType)
    148155    {
     156        timer.parent = GCTimer::s_currentGlobalTimer;
     157        GCTimer::s_currentGlobalTimer = &timer;
    149158    }
    150159    ~GCTimerScope()
    151160    {
    152         double delta = WTF::monotonicallyIncreasingTime() - m_start;
    153         m_timer->didFinishPhase(m_collectionType, delta);
    154     }
    155     GCTimer* m_timer;
    156     double m_start;
    157     HeapOperation m_collectionType;
     161        double delta = WTF::monotonicallyIncreasingTime() - start;
     162        timer.didFinishPhase(collectionType, delta);
     163        GCTimer::s_currentGlobalTimer = timer.parent;
     164    }
     165    GCTimer& timer;
     166    double start;
     167    HeapOperation collectionType;
    158168};
    159169
    160170struct GCCounter {
    161171    GCCounter(const char* name)
    162         : m_name(name)
    163         , m_count(0)
    164         , m_total(0)
    165         , m_min(10000000)
    166         , m_max(0)
     172        : name(name)
     173        , count(0)
     174        , total(0)
     175        , min(10000000)
     176        , max(0)
    167177    {
    168178    }
    169179   
    170     void count(size_t amount)
     180    void add(size_t amount)
    171181    {
    172         m_count++;
    173         m_total += amount;
    174         if (amount < m_min)
    175             m_min = amount;
    176         if (amount > m_max)
    177             m_max = amount;
     182        count++;
     183        total += amount;
     184        if (amount < min)
     185            min = amount;
     186        if (amount > max)
     187            max = amount;
    178188    }
    179189    ~GCCounter()
    180190    {
    181         dataLogF("[%d] %s: %zu values (avg. %zu, min. %zu, max. %zu)\n", getCurrentProcessID(), m_name, m_total, m_total / m_count, m_min, m_max);
    182     }
    183     const char* m_name;
    184     size_t m_count;
    185     size_t m_total;
    186     size_t m_min;
    187     size_t m_max;
     191        dataLogF("[%d] %s: %zu values (avg. %zu, min. %zu, max. %zu)\n", getCurrentProcessID(), name, total, total / count, min, max);
     192    }
     193    const char* name;
     194    size_t count;
     195    size_t total;
     196    size_t min;
     197    size_t max;
    188198};
    189199
    190 #define GCPHASE(name) DEFINE_GC_LOGGING_GLOBAL(GCTimer, name##Timer, (#name)); GCTimerScope name##TimerScope(&name##Timer, m_operationInProgress)
    191 #define GCCOUNTER(name, value) do { DEFINE_GC_LOGGING_GLOBAL(GCCounter, name##Counter, (#name)); name##Counter.count(value); } while (false)
     200#define GCPHASE(name) DEFINE_GC_LOGGING_GLOBAL(GCTimer, name##Timer, (#name)); GCTimerScope name##TimerScope(name##Timer, m_operationInProgress)
     201#define GCCOUNTER(name, value) do { DEFINE_GC_LOGGING_GLOBAL(GCCounter, name##Counter, (#name)); name##Counter.add(value); } while (false)
    192202   
    193203#else
  • trunk/Tools/ChangeLog

    r181801 r181821  
     12015-03-20  Mark Hahnenberg  <mhahnenb@gmail.com>
     2
     3        GCTimer should know keep track of nested GC phases
     4        https://bugs.webkit.org/show_bug.cgi?id=142675
     5
     6        Reviewed by Darin Adler.
     7
     8        Adds a tool to aid in parsing the GC phase timing output into a
     9        tree-like structure based on the parent-child relationships
     10        of nested GC phases.
     11
     12        * Scripts/parse-gc-phase-timings: Added.
     13        (Timing):
     14        (Timing.__init__):
     15        (Timing.__unicode__):
     16        (Timing.__str__):
     17        (Timing.__repr__):
     18        (parse_input):
     19        (print_timing_node):
     20        (print_timing_tree):
     21        (link_parents):
     22        (main):
     23
    1242015-03-20  Brent Fulgham  <bfulgham@apple.com>
    225
Note: See TracChangeset for help on using the changeset viewer.