Home | History | Annotate | Download | only in common
      1 /****************************************************************************
      2 * Copyright (C) 2014-2015 Intel Corporation.   All Rights Reserved.
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice (including the next
     12 * paragraph) shall be included in all copies or substantial portions of the
     13 * Software.
     14 *
     15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21 * IN THE SOFTWARE.
     22 *
     23 * @file rdtsc_buckets.cpp
     24 *
     25 * @brief implementation of rdtsc buckets.
     26 *
     27 * Notes:
     28 *
     29 ******************************************************************************/
     30 #include "rdtsc_buckets.h"
     31 #include <inttypes.h>
     32 
     33 #if defined(_WIN32)
     34 #define PATH_SEPARATOR "\\"
     35 #elif defined(__unix__) || defined(__APPLE__)
     36 #define PATH_SEPARATOR "/"
     37 #else
     38 #error "Unsupported platform"
     39 #endif
     40 
     41 THREAD UINT tlsThreadId = 0;
     42 
     43 BucketManager::~BucketManager()
     44 {
     45 }
     46 
     47 void BucketManager::RegisterThread(const std::string& name)
     48 {
     49 
     50     BUCKET_THREAD newThread;
     51     newThread.name = name;
     52     newThread.root.children.reserve(mBuckets.size());
     53     newThread.root.id = 0;
     54     newThread.root.pParent = nullptr;
     55     newThread.pCurrent = &newThread.root;
     56 
     57     mThreadMutex.lock();
     58 
     59     // assign unique thread id for this thread
     60     size_t id = mThreads.size();
     61     newThread.id = (UINT)id;
     62     tlsThreadId = (UINT)id;
     63 
     64     // store new thread
     65     mThreads.push_back(newThread);
     66 
     67     mThreadMutex.unlock();
     68 }
     69 
     70 UINT BucketManager::RegisterBucket(const BUCKET_DESC& desc)
     71 {
     72     mThreadMutex.lock();
     73     size_t id = mBuckets.size();
     74     mBuckets.push_back(desc);
     75     mThreadMutex.unlock();
     76     return (UINT)id;
     77 }
     78 
     79 void BucketManager::PrintBucket(FILE* f, UINT level, uint64_t threadCycles, uint64_t parentCycles, const BUCKET& bucket)
     80 {
     81     const char *arrows[] = {
     82         "",
     83         "|-> ",
     84         "    |-> ",
     85         "        |-> ",
     86         "            |-> ",
     87         "                |-> ",
     88         "                    |-> ",
     89         "                        |-> ",
     90         "                            |-> ",
     91     };
     92 
     93     // compute percent of total cycles used by this bucket
     94     float percentTotal = (float)((double)bucket.elapsed / (double)threadCycles * 100.0);
     95 
     96     // compute percent of parent cycles used by this bucket
     97     float percentParent = (float)((double)bucket.elapsed / (double)parentCycles * 100.0);
     98 
     99     // compute average cycle count per invocation
    100     uint64_t CPE = bucket.elapsed / bucket.count;
    101 
    102     BUCKET_DESC &desc = mBuckets[bucket.id];
    103 
    104     // construct hierarchy visualization
    105     char hier[80];
    106     strcpy(hier, arrows[level]);
    107     strcat(hier, desc.name.c_str());
    108 
    109     // print out
    110     fprintf(f, "%6.2f %6.2f %-10" PRIu64 " %-10" PRIu64 " %-10u %-10lu %-10u %s\n",
    111         percentTotal,
    112         percentParent,
    113         bucket.elapsed,
    114         CPE,
    115         bucket.count,
    116         (unsigned long)0,
    117         (uint32_t)0,
    118         hier
    119     );
    120 
    121     // dump all children of this bucket
    122     for (const BUCKET& child : bucket.children)
    123     {
    124         if (child.count)
    125         {
    126             PrintBucket(f, level + 1, threadCycles, bucket.elapsed, child);
    127         }
    128     }
    129 }
    130 
    131 void BucketManager::PrintThread(FILE* f, const BUCKET_THREAD& thread)
    132 {
    133     // print header
    134     fprintf(f, "\nThread %u (%s)\n", thread.id, thread.name.c_str());
    135     fprintf(f, " %%Tot   %%Par  Cycles     CPE        NumEvent   CPE2       NumEvent2  Bucket\n");
    136 
    137     // compute thread level total cycle counts across all buckets from root
    138     const BUCKET& root = thread.root;
    139     uint64_t totalCycles = 0;
    140     for (const BUCKET& child : root.children)
    141     {
    142         totalCycles += child.elapsed;
    143     }
    144 
    145     for (const BUCKET& child : root.children)
    146     {
    147         if (child.count)
    148         {
    149             PrintBucket(f, 0, totalCycles, totalCycles, child);
    150         }
    151     }
    152 }
    153 
    154 void BucketManager::PrintReport(const std::string& filename)
    155 {
    156     {
    157         FILE* f = fopen(filename.c_str(), "w");
    158 
    159         mThreadMutex.lock();
    160         for (const BUCKET_THREAD& thread : mThreads)
    161         {
    162             PrintThread(f, thread);
    163             fprintf(f, "\n");
    164         }
    165 
    166         mThreadMutex.unlock();
    167 
    168         fclose(f);
    169     }
    170 }
    171 
    172 
    173 void BucketManager::StartCapture()
    174 {
    175 
    176     printf("Capture Starting\n");
    177 
    178     mCapturing = true;
    179 }
    180 
    181 void BucketManager_StartBucket(BucketManager* pBucketMgr, uint32_t id)
    182 {
    183     pBucketMgr->StartBucket(id);
    184 }
    185 
    186 void BucketManager_StopBucket(BucketManager* pBucketMgr, uint32_t id)
    187 {
    188     pBucketMgr->StopBucket(id);
    189 }
    190