Ignore:
Timestamp:
Apr 30, 2009, 12:52:27 AM (16 years ago)
Author:
[email protected]
Message:

2009-04-30 Gavin Barraclough <[email protected]>

Reviewed by Maciej Stachowiak.

Add SamplingFlags mechanism.

This mechanism allows fine-grained JSC and JavaScript program aware
performance measurement. The mechanism provides a set of 32 flags,
numbered #1..#32. Flag #16 is initially set, and all other flags
are cleared. Flags may be set and cleared from within

Enable by setting ENABLE_SAMPLING_FLAGS to 1 in wtf/Platform.h.
Disabled by default, no performance impact. Flags may be modified
by calling SamplingFlags::setFlag() and SamplingFlags::clearFlag()
from within JSC implementation, or by calling setSamplingFlag() and
clearSamplingFlag() from JavaScript.

The flags are sampled with a frequency of 10000Hz, and the highest
set flag in recorded, allowing multiple events to be measured (with
the highest flag number representing the highest priority).

Disabled by default; no performance impact.

  • JavaScriptCore.exp:
  • bytecode/SamplingTool.cpp: (JSC::SamplingFlags::sample): (JSC::SamplingFlags::start): (JSC::SamplingFlags::stop): (JSC::SamplingThread::threadStartFunc): (JSC::SamplingThread::start): (JSC::SamplingThread::stop): (JSC::ScopeSampleRecord::sample): (JSC::SamplingTool::doRun): (JSC::SamplingTool::sample): (JSC::SamplingTool::start): (JSC::SamplingTool::stop):
  • bytecode/SamplingTool.h: (JSC::SamplingFlags::setFlag): (JSC::SamplingFlags::clearFlag): (JSC::SamplingTool::SamplingTool):
  • jsc.cpp: (GlobalObject::GlobalObject): (functionSetSamplingFlag): (functionClearSamplingFlag): (runWithScripts):
  • wtf/Platform.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/bytecode/SamplingTool.cpp

    r39993 r43047  
    4040namespace JSC {
    4141
     42#if ENABLE(SAMPLING_FLAGS)
     43
     44void SamplingFlags::sample()
     45{
     46    uint32_t mask = 1 << 31;
     47    unsigned index;
     48
     49    for (index = 0; index < 32; ++index) {
     50        if (mask & s_flags)
     51            break;
     52        mask >>= 1;
     53    }
     54
     55    s_flagCounts[32 - index]++;
     56}
     57
     58void SamplingFlags::start()
     59{
     60    for (unsigned i = 0; i <= 32; ++i)
     61        s_flagCounts[i] = 0;
     62}
     63void SamplingFlags::stop()
     64{
     65    uint64_t total = 0;
     66    for (unsigned i = 0; i <= 32; ++i)
     67        total += s_flagCounts[i];
     68
     69    printf("SamplingFlags: sample count with flags set:\n");
     70    for (unsigned i = 0; i <= 32; ++i)
     71        printf("  [ %02d ] : %lld\t\t(%03.2f%%)\n", i, s_flagCounts[i], (100.0 * s_flagCounts[i]) / total);
     72    printf("\n\n");
     73}
     74uint64_t SamplingFlags::s_flagCounts[33];
     75
     76#else
     77void SamplingFlags::start() {}
     78void SamplingFlags::stop() {}
     79#endif
     80
     81/*
     82  Start with flag 16 set.
     83  By doing this the monitoring of lower valued flags will be masked out
     84  until flag 16 is explictly cleared.
     85*/
     86uint32_t SamplingFlags::s_flags = 1 << 15;
     87
     88
     89#if PLATFORM(WIN_OS)
     90
     91static void sleepForMicroseconds(unsigned us)
     92{
     93    unsigned ms = us / 1000;
     94    if (us && !ms)
     95        ms = 1;
     96    Sleep(ms);
     97}
     98
     99#else
     100
     101static void sleepForMicroseconds(unsigned us)
     102{
     103    usleep(us);
     104}
     105
     106#endif
     107
     108static inline unsigned hertz2us(unsigned hertz)
     109{
     110    return 1000000 / hertz;
     111}
     112
     113
     114SamplingTool* SamplingTool::s_samplingTool = 0;
     115
     116
     117bool SamplingThread::s_running = false;
     118unsigned SamplingThread::s_hertz = 10000;
     119ThreadIdentifier SamplingThread::s_samplingThread;
     120
     121void* SamplingThread::threadStartFunc(void*)
     122{
     123    while (s_running) {
     124        sleepForMicroseconds(hertz2us(s_hertz));
     125
     126#if ENABLE(SAMPLING_FLAGS)
     127        SamplingFlags::sample();
     128#endif
     129#if ENABLE(OPCODE_SAMPLING)
     130        SamplingTool::sample();
     131#endif
     132    }
     133
     134    return 0;
     135}
     136
     137
     138void SamplingThread::start(unsigned hertz)
     139{
     140    ASSERT(!s_running);
     141    s_running = true;
     142    s_hertz = hertz;
     143
     144    s_samplingThread = createThread(threadStartFunc, 0, "JavaScriptCore::Sampler");
     145}
     146
     147void SamplingThread::stop()
     148{
     149    ASSERT(s_running);
     150    s_running = false;
     151    waitForThreadCompletion(s_samplingThread, 0);
     152}
     153
     154
    42155void ScopeSampleRecord::sample(CodeBlock* codeBlock, Instruction* vPC)
    43156{
     
    59172}
    60173
    61 #if PLATFORM(WIN_OS)
    62 
    63 static void sleepForMicroseconds(unsigned us)
    64 {
    65     unsigned ms = us / 1000;
    66     if (us && !ms)
    67         ms = 1;
    68     Sleep(ms);
    69 }
    70 
    71 #else
    72 
    73 static void sleepForMicroseconds(unsigned us)
    74 {
    75     usleep(us);
    76 }
    77 
    78 #endif
    79 
    80 static inline unsigned hertz2us(unsigned hertz)
    81 {
    82     return 1000000 / hertz;
    83 }
    84 
    85 void SamplingTool::run()
    86 {
    87     while (m_running) {
    88         sleepForMicroseconds(hertz2us(m_hertz));
    89 
    90         Sample sample(m_sample, m_codeBlock);
    91         ++m_sampleCount;
    92 
    93         if (sample.isNull())
    94             continue;
    95 
    96         if (!sample.inHostFunction()) {
    97             unsigned opcodeID = m_interpreter->getOpcodeID(sample.vPC()[0].u.opcode);
    98 
    99             ++m_opcodeSampleCount;
    100             ++m_opcodeSamples[opcodeID];
    101 
    102             if (sample.inCTIFunction())
    103                 m_opcodeSamplesInCTIFunctions[opcodeID]++;
    104         }
     174void SamplingTool::doRun()
     175{
     176    Sample sample(m_sample, m_codeBlock);
     177    ++m_sampleCount;
     178
     179    if (sample.isNull())
     180        return;
     181
     182    if (!sample.inHostFunction()) {
     183        unsigned opcodeID = m_interpreter->getOpcodeID(sample.vPC()[0].u.opcode);
     184
     185        ++m_opcodeSampleCount;
     186        ++m_opcodeSamples[opcodeID];
     187
     188        if (sample.inCTIFunction())
     189            m_opcodeSamplesInCTIFunctions[opcodeID]++;
     190    }
    105191
    106192#if ENABLE(CODEBLOCK_SAMPLING)
    107         MutexLocker locker(m_scopeSampleMapMutex);
    108         ScopeSampleRecord* record = m_scopeSampleMap->get(sample.codeBlock()->ownerNode());
    109         ASSERT(record);
    110         record->sample(sample.codeBlock(), sample.vPC());
    111 #endif
    112     }
    113 }
    114 
    115 void* SamplingTool::threadStartFunc(void* samplingTool)
    116 {
    117     reinterpret_cast<SamplingTool*>(samplingTool)->run();
    118     return 0;
     193    MutexLocker locker(m_scopeSampleMapMutex);
     194    ScopeSampleRecord* record = m_scopeSampleMap->get(sample.codeBlock()->ownerNode());
     195    ASSERT(record);
     196    record->sample(sample.codeBlock(), sample.vPC());
     197#endif
     198}
     199
     200void SamplingTool::sample()
     201{
     202    s_samplingTool->doRun();
    119203}
    120204
     
    125209}
    126210
    127 void SamplingTool::start(unsigned hertz)
    128 {
    129     ASSERT(!m_running);
    130     m_running = true;
    131     m_hertz = hertz;
    132 
    133     m_samplingThread = createThread(threadStartFunc, this, "JavaScriptCore::Sampler");
    134 }
    135 
    136 void SamplingTool::stop()
    137 {
    138     ASSERT(m_running);
    139     m_running = false;
    140     waitForThreadCompletion(m_samplingThread, 0);
     211void SamplingTool::setup()
     212{
     213    s_samplingTool = this;
    141214}
    142215
Note: See TracChangeset for help on using the changeset viewer.