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