]> git.cworth.org Git - apitrace/blob - common/trace_profiler.cpp
Improve internal format of profile results.
[apitrace] / common / trace_profiler.cpp
1 /**************************************************************************
2  *
3  * Copyright 2012 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 #include "trace_profiler.hpp"
27 #include "os_time.hpp"
28 #include <iostream>
29 #include <string.h>
30 #include <sstream>
31
32 namespace trace {
33 Profiler::Profiler()
34     : baseGpuTime(0),
35       baseCpuTime(0),
36       minCpuTime(1000),
37       cpuTimes(false),
38       gpuTimes(true),
39       pixelsDrawn(false)
40 {
41 }
42
43 Profiler::~Profiler()
44 {
45 }
46
47 void Profiler::setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_)
48 {
49     cpuTimes = cpuTimes_;
50     gpuTimes = gpuTimes_;
51     pixelsDrawn = pixelsDrawn_;
52
53     std::cout << "# call no gpu_start gpu_dura cpu_start cpu_dura pixels program name" << std::endl;
54 }
55
56 int64_t Profiler::getBaseCpuTime()
57 {
58     return baseCpuTime;
59 }
60
61 int64_t Profiler::getBaseGpuTime()
62 {
63     return baseGpuTime;
64 }
65
66 void Profiler::setBaseCpuTime(int64_t cpuStart)
67 {
68     baseCpuTime = cpuStart;
69 }
70
71 void Profiler::setBaseGpuTime(int64_t gpuStart)
72 {
73     baseGpuTime = gpuStart;
74 }
75
76 bool Profiler::hasBaseTimes()
77 {
78     return baseCpuTime != 0 || baseGpuTime != 0;
79 }
80
81 void Profiler::addCall(unsigned no,
82                        const char *name,
83                        unsigned program,
84                        int64_t pixels,
85                        int64_t gpuStart, int64_t gpuDuration,
86                        int64_t cpuStart, int64_t cpuDuration)
87 {
88     if (gpuTimes && gpuStart) {
89         gpuStart -= baseGpuTime;
90     } else {
91         gpuStart = 0;
92         gpuDuration = 0;
93     }
94
95     if (cpuTimes && cpuStart) {
96         double cpuTimeScale = 1.0E9 / os::timeFrequency;
97         cpuStart = (cpuStart - baseCpuTime) * cpuTimeScale;
98         cpuDuration = cpuDuration * cpuTimeScale;
99
100         if (cpuDuration < minCpuTime) {
101             return;
102         }
103     } else {
104         cpuStart = 0;
105         cpuDuration = 0;
106     }
107
108     if (!pixelsDrawn) {
109         pixels = 0;
110     }
111
112     std::cout << "call"
113               << " " << no
114               << " " << gpuStart
115               << " " << gpuDuration
116               << " " << cpuStart
117               << " " << cpuDuration
118               << " " << pixels
119               << " " << program
120               << " " << name
121               << std::endl;
122 }
123
124 void Profiler::addFrameEnd()
125 {
126     std::cout << "frame_end" << std::endl;
127 }
128
129 void Profiler::parseLine(const char* in, Profile* profile)
130 {
131     std::stringstream line(in, std::ios_base::in);
132     std::string type;
133     static int64_t lastGpuTime;
134     static int64_t lastCpuTime;
135
136     if (in[0] == '#' || strlen(in) < 4)
137         return;
138
139     if (profile->programs.size() == 0 && profile->calls.size() == 0 && profile->frames.size() == 0) {
140         lastGpuTime = 0;
141         lastCpuTime = 0;
142     }
143
144     line >> type;
145
146     if (type.compare("call") == 0) {
147         Profile::Call call;
148         unsigned programNo;
149
150         line >> call.no
151              >> call.gpuStart
152              >> call.gpuDuration
153              >> call.cpuStart
154              >> call.cpuDuration
155              >> call.pixels
156              >> programNo
157              >> call.name;
158
159         if (lastGpuTime < call.gpuStart + call.gpuDuration) {
160             lastGpuTime = call.gpuStart + call.gpuDuration;
161         }
162
163         if (lastCpuTime < call.cpuStart + call.cpuDuration) {
164             lastCpuTime = call.cpuStart + call.cpuDuration;
165         }
166
167         profile->calls.push_back(call);
168
169         if (call.pixels >= 0) {
170             if (profile->programs.size() <= programNo) {
171                 profile->programs.resize(programNo + 1);
172             }
173
174             Profile::Program& program = profile->programs[programNo];
175             program.cpuTotal += call.cpuDuration;
176             program.gpuTotal += call.gpuDuration;
177             program.pixelTotal += call.pixels;
178             program.calls.push_back(profile->calls.size() - 1);
179         }
180     } else if (type.compare("frame_end") == 0) {
181         Profile::Frame frame;
182         frame.no = profile->frames.size();
183
184         if (frame.no == 0) {
185             frame.gpuStart = 0;
186             frame.cpuStart = 0;
187             frame.calls.begin = 0;
188         } else {
189             frame.gpuStart = profile->frames.back().gpuStart + profile->frames.back().gpuDuration;
190             frame.cpuStart = profile->frames.back().cpuStart + profile->frames.back().cpuDuration;
191             frame.calls.begin = profile->frames.back().calls.end + 1;
192         }
193
194         frame.gpuDuration = lastGpuTime - frame.gpuStart;
195         frame.cpuDuration = lastCpuTime - frame.cpuStart;
196         frame.calls.end = profile->calls.size() - 1;
197
198         profile->frames.push_back(frame);
199     }
200 }
201 }