コード例 #1
0
void SamplingTool::dump(ExecState* exec)
{
    // Tidies up SunSpider output by removing short scripts - such a small number of samples would likely not be useful anyhow.
    if (m_sampleCount < 10)
        return;
    
    // (1) Build and sort 'opcodeSampleInfo' array.

    OpcodeSampleInfo opcodeSampleInfo[numOpcodeIDs];
    for (int i = 0; i < numOpcodeIDs; ++i) {
        opcodeSampleInfo[i].opcode = static_cast<OpcodeID>(i);
        opcodeSampleInfo[i].count = m_opcodeSamples[i];
        opcodeSampleInfo[i].countInCTIFunctions = m_opcodeSamplesInCTIFunctions[i];
    }

    qsort(opcodeSampleInfo, numOpcodeIDs, sizeof(OpcodeSampleInfo), compareOpcodeIndicesSampling);

    // (2) Print Opcode sampling results.

    printf("\nBytecode samples [*]\n");
    printf("                             sample   %% of       %% of     |   cti     cti %%\n");
    printf("opcode                       count     VM        total    |  count   of self\n");
    printf("-------------------------------------------------------   |  ----------------\n");

    for (int i = 0; i < numOpcodeIDs; ++i) {
        long long count = opcodeSampleInfo[i].count;
        if (!count)
            continue;

        OpcodeID opcodeID = opcodeSampleInfo[i].opcode;
        
        const char* opcodeName = opcodeNames[opcodeID];
        const char* opcodePadding = padOpcodeName(opcodeID, 28);
        double percentOfVM = (static_cast<double>(count) * 100) / m_opcodeSampleCount;
        double percentOfTotal = (static_cast<double>(count) * 100) / m_sampleCount;
        long long countInCTIFunctions = opcodeSampleInfo[i].countInCTIFunctions;
        double percentInCTIFunctions = (static_cast<double>(countInCTIFunctions) * 100) / count;
        fprintf(stdout, "%s:%s%-6lld %.3f%%\t%.3f%%\t  |   %-6lld %.3f%%\n", opcodeName, opcodePadding, count, percentOfVM, percentOfTotal, countInCTIFunctions, percentInCTIFunctions);
    }
    
    printf("\n[*] Samples inside host code are not charged to any Bytecode.\n\n");
    printf("\tSamples inside VM:\t\t%lld / %lld (%.3f%%)\n", m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_opcodeSampleCount) * 100) / m_sampleCount);
    printf("\tSamples inside host code:\t%lld / %lld (%.3f%%)\n\n", m_sampleCount - m_opcodeSampleCount, m_sampleCount, (static_cast<double>(m_sampleCount - m_opcodeSampleCount) * 100) / m_sampleCount);
    printf("\tsample count:\tsamples inside this opcode\n");
    printf("\t%% of VM:\tsample count / all opcode samples\n");
    printf("\t%% of total:\tsample count / all samples\n");
    printf("\t--------------\n");
    printf("\tcti count:\tsamples inside a CTI function called by this opcode\n");
    printf("\tcti %% of self:\tcti count / sample count\n");
    
#if ENABLE(CODEBLOCK_SAMPLING)

    // (3) Build and sort 'codeBlockSamples' array.

    int scopeCount = m_scopeSampleMap->size();
    Vector<ScopeSampleRecord*> codeBlockSamples(scopeCount);
    ScopeSampleRecordMap::iterator iter = m_scopeSampleMap->begin();
    for (int i = 0; i < scopeCount; ++i, ++iter)
        codeBlockSamples[i] = iter->second;

    qsort(codeBlockSamples.begin(), scopeCount, sizeof(ScopeSampleRecord*), compareScopeSampleRecords);

    // (4) Print data from 'codeBlockSamples' array.

    printf("\nCodeBlock samples\n\n"); 

    for (int i = 0; i < scopeCount; ++i) {
        ScopeSampleRecord* record = codeBlockSamples[i];
        CodeBlock* codeBlock = record->m_codeBlock;

        double blockPercent = (record->m_sampleCount * 100.0) / m_sampleCount;

        if (blockPercent >= 1) {
            //Instruction* code = codeBlock->instructions().begin();
            printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_scope->sourceURL().UTF8String().c_str(), codeBlock->lineNumberForBytecodeOffset(exec, 0), record->m_sampleCount, m_sampleCount, blockPercent);
            if (i < 10) {
                HashMap<unsigned,unsigned> lineCounts;
                codeBlock->dump(exec);

                printf("    Opcode and line number samples [*]\n\n");
                for (unsigned op = 0; op < record->m_size; ++op) {
                    int count = record->m_samples[op];
                    if (count) {
                        printf("    [% 4d] has sample count: % 4d\n", op, count);
                        unsigned line = codeBlock->lineNumberForBytecodeOffset(exec, op);
                        lineCounts.set(line, (lineCounts.contains(line) ? lineCounts.get(line) : 0) + count);
                    }
                }
                printf("\n");

                int linesCount = lineCounts.size();
                Vector<LineCountInfo> lineCountInfo(linesCount);
                int lineno = 0;
                for (HashMap<unsigned,unsigned>::iterator iter = lineCounts.begin(); iter != lineCounts.end(); ++iter, ++lineno) {
                    lineCountInfo[lineno].line = iter->first;
                    lineCountInfo[lineno].count = iter->second;
                }

                qsort(lineCountInfo.begin(), linesCount, sizeof(LineCountInfo), compareLineCountInfoSampling);

                for (lineno = 0; lineno < linesCount; ++lineno) {
                    printf("    Line #%d has sample count %d.\n", lineCountInfo[lineno].line, lineCountInfo[lineno].count);
                }
                printf("\n");
                printf("    [*] Samples inside host code are charged to the calling Bytecode.\n");
                printf("        Samples on a call / return boundary are not charged to a specific opcode or line.\n\n");
                printf("            Samples on a call / return boundary: %d / %d (%.3f%%)\n\n", record->m_sampleCount - record->m_opcodeSampleCount, record->m_sampleCount, (static_cast<double>(record->m_sampleCount - record->m_opcodeSampleCount) * 100) / record->m_sampleCount);
            }
        }
    }
#else
    UNUSED_PARAM(exec);
#endif
}
コード例 #2
0
ファイル: Opcode.cpp プロジェクト: AngelkPetkov/tijscore
OpcodeStats::~OpcodeStats()
{
    long long totalInstructions = 0;
    for (int i = 0; i < numOpcodeIDs; ++i)
        totalInstructions += opcodeCounts[i];
    
    long long totalInstructionPairs = 0;
    for (int i = 0; i < numOpcodeIDs; ++i)
        for (int j = 0; j < numOpcodeIDs; ++j)
            totalInstructionPairs += opcodePairCounts[i][j];

    FixedArray<int, numOpcodeIDs> sortedIndices;
    for (int i = 0; i < numOpcodeIDs; ++i)
        sortedIndices[i] = i;
    qsort(sortedIndices.data(), numOpcodeIDs, sizeof(int), compareOpcodeIndices);
    
    pair<int, int> sortedPairIndices[numOpcodeIDs * numOpcodeIDs];
    pair<int, int>* currentPairIndex = sortedPairIndices;
    for (int i = 0; i < numOpcodeIDs; ++i)
        for (int j = 0; j < numOpcodeIDs; ++j)
            *(currentPairIndex++) = make_pair(i, j);
    qsort(sortedPairIndices, numOpcodeIDs * numOpcodeIDs, sizeof(pair<int, int>), compareOpcodePairIndices);
    
    printf("\nExecuted opcode statistics\n"); 
    
    printf("Total instructions executed: %lld\n\n", totalInstructions);

    printf("All opcodes by frequency:\n\n");

    for (int i = 0; i < numOpcodeIDs; ++i) {
        int index = sortedIndices[i];
        printf("%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCounts[index], ((double) opcodeCounts[index]) / ((double) totalInstructions) * 100.0);    
    }
    
    printf("\n");
    printf("2-opcode sequences by frequency: %lld\n\n", totalInstructions);
    
    for (int i = 0; i < numOpcodeIDs * numOpcodeIDs; ++i) {
        pair<int, int> indexPair = sortedPairIndices[i];
        long long count = opcodePairCounts[indexPair.first][indexPair.second];
        
        if (!count)
            break;
        
        printf("%s%s %s:%s %lld %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), count, ((double) count) / ((double) totalInstructionPairs) * 100.0);
    }
    
    printf("\n");
    printf("Most common opcodes and sequences:\n");

    for (int i = 0; i < numOpcodeIDs; ++i) {
        int index = sortedIndices[i];
        long long opcodeCount = opcodeCounts[index];
        double opcodeProportion = ((double) opcodeCount) / ((double) totalInstructions);
        if (opcodeProportion < 0.0001)
            break;
        printf("\n%s:%s %lld - %.2f%%\n", opcodeNames[index], padOpcodeName((OpcodeID)index, 28), opcodeCount, opcodeProportion * 100.0);

        for (int j = 0; j < numOpcodeIDs * numOpcodeIDs; ++j) {
            pair<int, int> indexPair = sortedPairIndices[j];
            long long pairCount = opcodePairCounts[indexPair.first][indexPair.second];
            double pairProportion = ((double) pairCount) / ((double) totalInstructionPairs);
        
            if (!pairCount || pairProportion < 0.0001 || pairProportion < opcodeProportion / 100)
                break;

            if (indexPair.first != index && indexPair.second != index)
                continue;

            printf("    %s%s %s:%s %lld - %.2f%%\n", opcodeNames[indexPair.first], padOpcodeName((OpcodeID)indexPair.first, 28), opcodeNames[indexPair.second], padOpcodeName((OpcodeID)indexPair.second, 28), pairCount, pairProportion * 100.0);
        }
        
    }
    printf("\n");
}