xref: /haiku/src/bin/debug/profile/BasicProfileResult.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
1 /*
2  * Copyright 2008-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "BasicProfileResult.h"
8 
9 #include <stdio.h>
10 
11 #include <algorithm>
12 #include <new>
13 
14 #include "Options.h"
15 #include "ProfiledEntity.h"
16 
17 
18 struct HitSymbol {
19 	int64		hits;
20 	Symbol*		symbol;
21 	image_id	imageID;
22 
23 	inline bool operator<(const HitSymbol& other) const
24 	{
25 		return hits > other.hits;
26 	}
27 };
28 
29 
30 // #pragma mark - BasicImageProfileResult
31 
32 
33 BasicImageProfileResult::BasicImageProfileResult(SharedImage* image,
34 	image_id id)
35 	:
36 	ImageProfileResult(image, id),
37 	fSymbolHits(NULL),
38 	fUnknownHits(0)
39 {
40 }
41 
42 
43 BasicImageProfileResult::~BasicImageProfileResult()
44 {
45 }
46 
47 
48 status_t
49 BasicImageProfileResult::Init()
50 {
51 	int32 symbolCount = fImage->SymbolCount();
52 	fSymbolHits = new(std::nothrow) int64[symbolCount];
53 	if (fSymbolHits == NULL)
54 		return B_NO_MEMORY;
55 
56 	memset(fSymbolHits, 0, 8 * symbolCount);
57 
58 	return B_OK;
59 }
60 
61 
62 bool
63 BasicImageProfileResult::AddHit(addr_t address)
64 {
65 	int32 symbolIndex = fImage->FindSymbol(address);
66 	if (symbolIndex < 0)
67 		return false;
68 
69 	fSymbolHits[symbolIndex]++;
70 	fTotalHits++;
71 
72 	return true;
73 }
74 
75 
76 void
77 BasicImageProfileResult::AddUnknownHit()
78 {
79 	fUnknownHits++;
80 	fTotalHits++;
81 }
82 
83 
84 void
85 BasicImageProfileResult::AddSymbolHit(int32 symbolIndex)
86 {
87 	fSymbolHits[symbolIndex]++;
88 }
89 
90 
91 void
92 BasicImageProfileResult::AddImageHit()
93 {
94 	fTotalHits++;
95 }
96 
97 
98 const int64*
99 BasicImageProfileResult::SymbolHits() const
100 {
101 	return fSymbolHits;
102 }
103 
104 
105 int64
106 BasicImageProfileResult::UnknownHits() const
107 {
108 	return fUnknownHits;
109 }
110 
111 
112 // #pragma mark - BasicProfileResult
113 
114 
115 BasicProfileResult::BasicProfileResult()
116 	:
117 	fTotalTicks(0),
118 	fUnkownTicks(0),
119 	fDroppedTicks(0),
120 	fTotalSampleCount(0)
121 {
122 }
123 
124 
125 void
126 BasicProfileResult::AddDroppedTicks(int32 dropped)
127 {
128 	fDroppedTicks += dropped;
129 }
130 
131 
132 void
133 BasicProfileResult::PrintResults(ImageProfileResultContainer* container)
134 {
135 	// get hit images
136 	BasicImageProfileResult* images[container->CountImages()];
137 	int32 imageCount = GetHitImages(container, images);
138 
139 	// count symbols
140 	int32 symbolCount = 0;
141 	for (int32 k = 0; k < imageCount; k++) {
142 		BasicImageProfileResult* image = images[k];
143 		if (image->TotalHits() > image->UnknownHits())
144 			symbolCount += image->GetImage()->SymbolCount();
145 	}
146 
147 	// find and sort the hit symbols
148 	HitSymbol hitSymbols[symbolCount];
149 	int32 hitSymbolCount = 0;
150 
151 	for (int32 k = 0; k < imageCount; k++) {
152 		BasicImageProfileResult* image = images[k];
153 		if (image->TotalHits() > image->UnknownHits()) {
154 			Symbol** symbols = image->GetImage()->Symbols();
155 			const int64* symbolHits = image->SymbolHits();
156 			int32 imageSymbolCount = image->GetImage()->SymbolCount();
157 			for (int32 i = 0; i < imageSymbolCount; i++) {
158 				if (symbolHits[i] > 0) {
159 					HitSymbol& hitSymbol = hitSymbols[hitSymbolCount++];
160 					hitSymbol.hits = symbolHits[i];
161 					hitSymbol.symbol = symbols[i];
162 					hitSymbol.imageID = image->ID();
163 				}
164 			}
165 		}
166 	}
167 
168 	if (hitSymbolCount > 1)
169 		std::sort(hitSymbols, hitSymbols + hitSymbolCount);
170 
171 	int64 totalTicks = fTotalTicks;
172 	fprintf(gOptions.output, "\nprofiling results for %s \"%s\" "
173 		"(%" B_PRId32 "):\n", fEntity->EntityType(), fEntity->EntityName(),
174 		fEntity->EntityID());
175 	fprintf(gOptions.output, "  tick interval:  %lld us\n", fInterval);
176 	fprintf(gOptions.output, "  total ticks:    %lld (%lld us)\n",
177 		totalTicks, totalTicks * fInterval);
178 	if (totalTicks == 0)
179 		totalTicks = 1;
180 	fprintf(gOptions.output, "  unknown ticks:  %lld (%lld us, %6.2f%%)\n",
181 		fUnkownTicks, fUnkownTicks * fInterval,
182 		100.0 * fUnkownTicks / totalTicks);
183 	fprintf(gOptions.output, "  dropped ticks:  %lld (%lld us, %6.2f%%)\n",
184 		fDroppedTicks, fDroppedTicks * fInterval,
185 		100.0 * fDroppedTicks / totalTicks);
186 	if (gOptions.analyze_full_stack) {
187 		fprintf(gOptions.output, "  samples/tick:   %.1f\n",
188 			(double)fTotalSampleCount / totalTicks);
189 	}
190 
191 	if (imageCount > 0) {
192 		fprintf(gOptions.output, "\n");
193 		fprintf(gOptions.output, "        hits     unknown    image\n");
194 		fprintf(gOptions.output, "  ---------------------------------------"
195 			"---------------------------------------\n");
196 		for (int32 k = 0; k < imageCount; k++) {
197 			BasicImageProfileResult* image = images[k];
198 			fprintf(gOptions.output, "  %10lld  %10lld  %7ld %s\n",
199 				image->TotalHits(), image->UnknownHits(),
200 				image->ID(), image->GetImage()->Name());
201 		}
202 	}
203 
204 	if (hitSymbolCount > 0) {
205 		fprintf(gOptions.output, "\n");
206 		fprintf(gOptions.output, "        hits       in us    in %%   "
207 			"image  function\n");
208 		fprintf(gOptions.output, "  ---------------------------------------"
209 			"---------------------------------------\n");
210 		for (int32 i = 0; i < hitSymbolCount; i++) {
211 			const HitSymbol& hitSymbol = hitSymbols[i];
212 			const Symbol* symbol = hitSymbol.symbol;
213 			fprintf(gOptions.output, "  %10lld  %10lld  %6.2f  %6ld  %s\n",
214 				hitSymbol.hits, hitSymbol.hits * fInterval,
215 				100.0 * hitSymbol.hits / totalTicks, hitSymbol.imageID,
216 				symbol->Name());
217 		}
218 	} else
219 		fprintf(gOptions.output, "  no functions were hit\n");
220 }
221 
222 
223 status_t
224 BasicProfileResult::GetImageProfileResult(SharedImage* image, image_id id,
225 	ImageProfileResult*& _imageResult)
226 {
227 	BasicImageProfileResult* result
228 		= new(std::nothrow) BasicImageProfileResult(image, id);
229 	if (result == NULL)
230 		return B_NO_MEMORY;
231 
232 	status_t error = result->Init();
233 	if (error != B_OK) {
234 		delete result;
235 		return error;
236 	}
237 
238 	_imageResult = result;
239 	return B_OK;
240 }
241 
242 
243 // #pragma mark - InclusiveProfileResult
244 
245 
246 void
247 InclusiveProfileResult::AddSamples(ImageProfileResultContainer* container,
248 	addr_t* samples, int32 sampleCount)
249 {
250 	// Sort the samples. This way hits of the same symbol are
251 	// successive and we can avoid incrementing the hit count of the
252 	// same symbol twice. Same for images.
253 	std::sort(samples, samples + sampleCount);
254 
255 	int32 unknownSamples = 0;
256 	BasicImageProfileResult* previousImage = NULL;
257 	int32 previousSymbol = -1;
258 
259 	for (int32 i = 0; i < sampleCount; i++) {
260 		addr_t address = samples[i];
261 		addr_t loadDelta;
262 		BasicImageProfileResult* image = static_cast<BasicImageProfileResult*>(
263 			container->FindImage(address, loadDelta));
264 		int32 symbol = -1;
265 		if (image != NULL) {
266 			symbol = image->GetImage()->FindSymbol(address - loadDelta);
267 			if (symbol < 0) {
268 				// TODO: Count unknown image hits?
269 			} else if (image != previousImage || symbol != previousSymbol)
270 				image->AddSymbolHit(symbol);
271 
272 			if (image != previousImage)
273 				image->AddImageHit();
274 		} else
275 			unknownSamples++;
276 
277 		previousImage = image;
278 		previousSymbol = symbol;
279 	}
280 
281 	if (unknownSamples == sampleCount)
282 		fUnkownTicks++;
283 
284 	fTotalTicks++;
285 	fTotalSampleCount += sampleCount;
286 }
287 
288 
289 // #pragma mark - ExclusiveProfileResult
290 
291 
292 void
293 ExclusiveProfileResult::AddSamples(ImageProfileResultContainer* container,
294 	addr_t* samples, int32 sampleCount)
295 {
296 	BasicImageProfileResult* image = NULL;
297 		// the image in which we hit a symbol
298 	BasicImageProfileResult* firstImage = NULL;
299 		// the first image we hit, != image if no symbol was hit
300 
301 	for (int32 k = 0; k < sampleCount; k++) {
302 		addr_t address = samples[k];
303 		addr_t loadDelta;
304 		image = static_cast<BasicImageProfileResult*>(
305 			container->FindImage(address, loadDelta));
306 		if (image != NULL) {
307 			if (image->AddHit(address - loadDelta))
308 				break;
309 			if (firstImage == NULL)
310 				firstImage = image;
311 		}
312 	}
313 
314 	if (image == NULL) {
315 		if (firstImage != NULL)
316 			firstImage->AddUnknownHit();
317 		else
318 			fUnkownTicks++;
319 	}
320 
321 	fTotalTicks++;
322 	fTotalSampleCount += sampleCount;
323 }
324