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