1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
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:
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
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
23 * @file rdtsc_buckets.cpp
25 * @brief implementation of rdtsc buckets.
29 ******************************************************************************/
30 #include "rdtsc_buckets.h"
34 #define PATH_SEPARATOR "\\"
35 #elif defined(__unix__) || defined(__APPLE__)
36 #define PATH_SEPARATOR "/"
38 #error "Unsupported platform"
41 THREAD UINT tlsThreadId
= 0;
43 BucketManager::~BucketManager()
47 void BucketManager::RegisterThread(const std::string
& name
)
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
;
59 // assign unique thread id for this thread
60 size_t id
= mThreads
.size();
61 newThread
.id
= (UINT
)id
;
62 tlsThreadId
= (UINT
)id
;
65 mThreads
.push_back(newThread
);
67 mThreadMutex
.unlock();
70 UINT
BucketManager::RegisterBucket(const BUCKET_DESC
& desc
)
73 size_t id
= mBuckets
.size();
74 mBuckets
.push_back(desc
);
75 mThreadMutex
.unlock();
79 void BucketManager::PrintBucket(
80 FILE* f
, UINT level
, uint64_t threadCycles
, uint64_t parentCycles
, const BUCKET
& bucket
)
82 const char* arrows
[] = {
94 // compute percent of total cycles used by this bucket
95 float percentTotal
= (float)((double)bucket
.elapsed
/ (double)threadCycles
* 100.0);
97 // compute percent of parent cycles used by this bucket
98 float percentParent
= (float)((double)bucket
.elapsed
/ (double)parentCycles
* 100.0);
100 // compute average cycle count per invocation
101 uint64_t CPE
= bucket
.elapsed
/ bucket
.count
;
103 BUCKET_DESC
& desc
= mBuckets
[bucket
.id
];
105 // construct hierarchy visualization
106 std::string str
= arrows
[level
];
109 strcpy_s(hier
, sizeof(hier
)-1, str
.c_str());
113 "%6.2f %6.2f %-10" PRIu64
" %-10" PRIu64
" %-10u %-10lu %-10u %s\n",
123 // dump all children of this bucket
124 for (const BUCKET
& child
: bucket
.children
)
128 PrintBucket(f
, level
+ 1, threadCycles
, bucket
.elapsed
, child
);
133 void BucketManager::PrintThread(FILE* f
, const BUCKET_THREAD
& thread
)
136 fprintf(f
, "\nThread %u (%s)\n", thread
.id
, thread
.name
.c_str());
137 fprintf(f
, " %%Tot %%Par Cycles CPE NumEvent CPE2 NumEvent2 Bucket\n");
139 // compute thread level total cycle counts across all buckets from root
140 const BUCKET
& root
= thread
.root
;
141 uint64_t totalCycles
= 0;
142 for (const BUCKET
& child
: root
.children
)
144 totalCycles
+= child
.elapsed
;
147 for (const BUCKET
& child
: root
.children
)
151 PrintBucket(f
, 0, totalCycles
, totalCycles
, child
);
156 void BucketManager::PrintReport(const std::string
& filename
)
159 FILE* f
= fopen(filename
.c_str(), "w");
163 for (const BUCKET_THREAD
& thread
: mThreads
)
165 PrintThread(f
, thread
);
169 mThreadMutex
.unlock();
176 void BucketManager::StartCapture()
179 printf("Capture Starting\n");
184 void BucketManager_StartBucket(BucketManager
* pBucketMgr
, uint32_t id
)
186 pBucketMgr
->StartBucket(id
);
189 void BucketManager_StopBucket(BucketManager
* pBucketMgr
, uint32_t id
)
191 pBucketMgr
->StopBucket(id
);