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