hist.c 22.7 KB
Newer Older
1
#include "util.h"
2
#include "build-id.h"
3
#include "hist.h"
4 5
#include "session.h"
#include "sort.h"
6
#include "evsel.h"
7
#include <math.h>
8

9 10 11 12
static bool hists__filter_entry_by_dso(struct hists *hists,
				       struct hist_entry *he);
static bool hists__filter_entry_by_thread(struct hists *hists,
					  struct hist_entry *he);
13 14
static bool hists__filter_entry_by_symbol(struct hists *hists,
					  struct hist_entry *he);
15

16 17
struct callchain_param	callchain_param = {
	.mode	= CHAIN_GRAPH_REL,
18
	.min_percent = 0.5,
19 20
	.order  = ORDER_CALLEE,
	.key	= CCKEY_FUNCTION
21 22
};

23
u16 hists__col_len(struct hists *hists, enum hist_column col)
24
{
25
	return hists->col_len[col];
26 27
}

28
void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len)
29
{
30
	hists->col_len[col] = len;
31 32
}

33
bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len)
34
{
35 36
	if (len > hists__col_len(hists, col)) {
		hists__set_col_len(hists, col, len);
37 38 39 40 41
		return true;
	}
	return false;
}

42
void hists__reset_col_len(struct hists *hists)
43 44 45 46
{
	enum hist_column col;

	for (col = 0; col < HISTC_NR_COLS; ++col)
47
		hists__set_col_len(hists, col, 0);
48 49
}

50 51 52 53 54 55 56 57 58 59
static void hists__set_unres_dso_col_len(struct hists *hists, int dso)
{
	const unsigned int unresolved_col_width = BITS_PER_LONG / 4;

	if (hists__col_len(hists, dso) < unresolved_col_width &&
	    !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
	    !symbol_conf.dso_list)
		hists__set_col_len(hists, dso, unresolved_col_width);
}

60
void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
61
{
62
	const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
63
	int symlen;
64 65
	u16 len;

66 67 68 69 70 71 72 73 74 75 76
	/*
	 * +4 accounts for '[x] ' priv level info
	 * +2 accounts for 0x prefix on raw addresses
	 * +3 accounts for ' y ' symtab origin info
	 */
	if (h->ms.sym) {
		symlen = h->ms.sym->namelen + 4;
		if (verbose)
			symlen += BITS_PER_LONG / 4 + 2 + 3;
		hists__new_col_len(hists, HISTC_SYMBOL, symlen);
	} else {
77 78
		symlen = unresolved_col_width + 4 + 2;
		hists__new_col_len(hists, HISTC_SYMBOL, symlen);
79
		hists__set_unres_dso_col_len(hists, HISTC_DSO);
80
	}
81 82

	len = thread__comm_len(h->thread);
83 84
	if (hists__new_col_len(hists, HISTC_COMM, len))
		hists__set_col_len(hists, HISTC_THREAD, len + 6);
85 86 87

	if (h->ms.map) {
		len = dso__name_len(h->ms.map->dso);
88
		hists__new_col_len(hists, HISTC_DSO, len);
89
	}
90

91 92 93
	if (h->parent)
		hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen);

94 95 96
	if (h->branch_info) {
		if (h->branch_info->from.sym) {
			symlen = (int)h->branch_info->from.sym->namelen + 4;
97 98
			if (verbose)
				symlen += BITS_PER_LONG / 4 + 2 + 3;
99 100 101 102 103 104 105 106 107 108 109 110
			hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);

			symlen = dso__name_len(h->branch_info->from.map->dso);
			hists__new_col_len(hists, HISTC_DSO_FROM, symlen);
		} else {
			symlen = unresolved_col_width + 4 + 2;
			hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);
			hists__set_unres_dso_col_len(hists, HISTC_DSO_FROM);
		}

		if (h->branch_info->to.sym) {
			symlen = (int)h->branch_info->to.sym->namelen + 4;
111 112
			if (verbose)
				symlen += BITS_PER_LONG / 4 + 2 + 3;
113 114 115 116 117 118 119 120 121 122
			hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);

			symlen = dso__name_len(h->branch_info->to.map->dso);
			hists__new_col_len(hists, HISTC_DSO_TO, symlen);
		} else {
			symlen = unresolved_col_width + 4 + 2;
			hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
			hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
		}
	}
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

	if (h->mem_info) {
		if (h->mem_info->daddr.sym) {
			symlen = (int)h->mem_info->daddr.sym->namelen + 4
			       + unresolved_col_width + 2;
			hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
					   symlen);
		} else {
			symlen = unresolved_col_width + 4 + 2;
			hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
					   symlen);
		}
		if (h->mem_info->daddr.map) {
			symlen = dso__name_len(h->mem_info->daddr.map->dso);
			hists__new_col_len(hists, HISTC_MEM_DADDR_DSO,
					   symlen);
		} else {
			symlen = unresolved_col_width + 4 + 2;
			hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
		}
	} else {
		symlen = unresolved_col_width + 4 + 2;
		hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
		hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
	}

	hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
	hists__new_col_len(hists, HISTC_MEM_TLB, 22);
	hists__new_col_len(hists, HISTC_MEM_SNOOP, 12);
	hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
	hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
	hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
155 156 157 158

	if (h->transaction)
		hists__new_col_len(hists, HISTC_TRANSACTION,
				   hist_entry__transaction_len());
159 160
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
void hists__output_recalc_col_len(struct hists *hists, int max_rows)
{
	struct rb_node *next = rb_first(&hists->entries);
	struct hist_entry *n;
	int row = 0;

	hists__reset_col_len(hists);

	while (next && row++ < max_rows) {
		n = rb_entry(next, struct hist_entry, rb_node);
		if (!n->filtered)
			hists__calc_col_len(hists, n);
		next = rb_next(&n->rb_node);
	}
}

177 178
static void he_stat__add_cpumode_period(struct he_stat *he_stat,
					unsigned int cpumode, u64 period)
179
{
180
	switch (cpumode) {
181
	case PERF_RECORD_MISC_KERNEL:
182
		he_stat->period_sys += period;
183 184
		break;
	case PERF_RECORD_MISC_USER:
185
		he_stat->period_us += period;
186 187
		break;
	case PERF_RECORD_MISC_GUEST_KERNEL:
188
		he_stat->period_guest_sys += period;
189 190
		break;
	case PERF_RECORD_MISC_GUEST_USER:
191
		he_stat->period_guest_us += period;
192 193 194 195 196 197
		break;
	default:
		break;
	}
}

198 199
static void he_stat__add_period(struct he_stat *he_stat, u64 period,
				u64 weight)
200
{
201

202
	he_stat->period		+= period;
203
	he_stat->weight		+= weight;
204 205 206 207 208 209 210 211 212 213 214
	he_stat->nr_events	+= 1;
}

static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
{
	dest->period		+= src->period;
	dest->period_sys	+= src->period_sys;
	dest->period_us		+= src->period_us;
	dest->period_guest_sys	+= src->period_guest_sys;
	dest->period_guest_us	+= src->period_guest_us;
	dest->nr_events		+= src->nr_events;
215
	dest->weight		+= src->weight;
216 217
}

218
static void he_stat__decay(struct he_stat *he_stat)
219
{
220 221
	he_stat->period = (he_stat->period * 7) / 8;
	he_stat->nr_events = (he_stat->nr_events * 7) / 8;
222
	/* XXX need decay for weight too? */
223 224 225 226
}

static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
{
227
	u64 prev_period = he->stat.period;
228
	u64 diff;
229 230

	if (prev_period == 0)
231
		return true;
232

233
	he_stat__decay(&he->stat);
234

235 236 237
	diff = prev_period - he->stat.period;

	hists->stats.total_period -= diff;
238
	if (!he->filtered)
239
		hists->stats.total_non_filtered_period -= diff;
240

241
	return he->stat.period == 0;
242 243
}

244
void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
245 246 247 248 249 250 251
{
	struct rb_node *next = rb_first(&hists->entries);
	struct hist_entry *n;

	while (next) {
		n = rb_entry(next, struct hist_entry, rb_node);
		next = rb_next(&n->rb_node);
252 253 254 255 256
		/*
		 * We may be annotating this, for instance, so keep it here in
		 * case some it gets new samples, we'll eventually free it when
		 * the user stops browsing and it agains gets fully decayed.
		 */
257 258 259 260
		if (((zap_user && n->level == '.') ||
		     (zap_kernel && n->level != '.') ||
		     hists__decay_entry(hists, n)) &&
		    !n->used) {
261 262
			rb_erase(&n->rb_node, &hists->entries);

263
			if (sort__need_collapse)
264 265 266
				rb_erase(&n->rb_node_in, &hists->entries_collapsed);

			--hists->nr_entries;
267 268 269 270
			if (!n->filtered)
				--hists->nr_non_filtered_entries;

			hist_entry__free(n);
271 272 273 274
		}
	}
}

275
/*
276
 * histogram, sorted on item, collects periods
277 278
 */

279 280
static struct hist_entry *hist_entry__new(struct hist_entry *template)
{
281
	size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
282
	struct hist_entry *he = zalloc(sizeof(*he) + callchain_size);
283

284 285
	if (he != NULL) {
		*he = *template;
286

287 288
		if (he->ms.map)
			he->ms.map->referenced = true;
289 290

		if (he->branch_info) {
291 292
			/*
			 * This branch info is (a part of) allocated from
293
			 * sample__resolve_bstack() and will be freed after
294 295 296 297 298 299 300 301 302 303 304
			 * adding new entries.  So we need to save a copy.
			 */
			he->branch_info = malloc(sizeof(*he->branch_info));
			if (he->branch_info == NULL) {
				free(he);
				return NULL;
			}

			memcpy(he->branch_info, template->branch_info,
			       sizeof(*he->branch_info));

305 306 307 308 309 310
			if (he->branch_info->from.map)
				he->branch_info->from.map->referenced = true;
			if (he->branch_info->to.map)
				he->branch_info->to.map->referenced = true;
		}

311 312 313 314 315 316 317
		if (he->mem_info) {
			if (he->mem_info->iaddr.map)
				he->mem_info->iaddr.map->referenced = true;
			if (he->mem_info->daddr.map)
				he->mem_info->daddr.map->referenced = true;
		}

318
		if (symbol_conf.use_callchain)
319
			callchain_init(he->callchain);
320 321

		INIT_LIST_HEAD(&he->pairs.node);
322 323
	}

324
	return he;
325 326
}

327 328 329 330 331 332 333
static u8 symbol__parent_filter(const struct symbol *parent)
{
	if (symbol_conf.exclude_other && parent == NULL)
		return 1 << HIST_FILTER__PARENT;
	return 0;
}

334
static struct hist_entry *add_hist_entry(struct hists *hists,
335 336
					 struct hist_entry *entry,
					 struct addr_location *al)
337
{
338
	struct rb_node **p;
339 340
	struct rb_node *parent = NULL;
	struct hist_entry *he;
341
	int64_t cmp;
342 343
	u64 period = entry->stat.period;
	u64 weight = entry->stat.weight;
344

345 346
	p = &hists->entries_in->rb_node;

347 348
	while (*p != NULL) {
		parent = *p;
349
		he = rb_entry(parent, struct hist_entry, rb_node_in);
350

351 352 353 354 355 356 357
		/*
		 * Make sure that it receives arguments in a same order as
		 * hist_entry__collapse() so that we can use an appropriate
		 * function when searching an entry regardless which sort
		 * keys were used.
		 */
		cmp = hist_entry__cmp(he, entry);
358 359

		if (!cmp) {
360
			he_stat__add_period(&he->stat, period, weight);
361

362
			/*
363
			 * This mem info was allocated from sample__resolve_mem
364 365
			 * and will not be used anymore.
			 */
366
			zfree(&entry->mem_info);
367

368 369 370 371 372 373 374 375 376 377 378
			/* If the map of an existing hist_entry has
			 * become out-of-date due to an exec() or
			 * similar, update it.  Otherwise we will
			 * mis-adjust symbol addresses when computing
			 * the history counter to increment.
			 */
			if (he->ms.map != entry->ms.map) {
				he->ms.map = entry->ms.map;
				if (he->ms.map)
					he->ms.map->referenced = true;
			}
379
			goto out;
380 381 382 383 384 385 386 387
		}

		if (cmp < 0)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

388
	he = hist_entry__new(entry);
389
	if (!he)
390
		return NULL;
391 392 393

	rb_link_node(&he->rb_node_in, parent, p);
	rb_insert_color(&he->rb_node_in, hists->entries_in);
394
out:
395
	he_stat__add_cpumode_period(&he->stat, al->cpumode, period);
396 397 398
	return he;
}

399
struct hist_entry *__hists__add_entry(struct hists *hists,
400
				      struct addr_location *al,
401 402 403 404
				      struct symbol *sym_parent,
				      struct branch_info *bi,
				      struct mem_info *mi,
				      u64 period, u64 weight, u64 transaction)
405 406 407
{
	struct hist_entry entry = {
		.thread	= al->thread,
408
		.comm = thread__comm(al->thread),
409 410 411 412 413 414 415
		.ms = {
			.map	= al->map,
			.sym	= al->sym,
		},
		.cpu	= al->cpu,
		.ip	= al->addr,
		.level	= al->level,
416
		.stat = {
417
			.nr_events = 1,
418
			.period	= period,
419
			.weight = weight,
420
		},
421
		.parent = sym_parent,
422
		.filtered = symbol__parent_filter(sym_parent) | al->filtered,
423
		.hists	= hists,
424 425
		.branch_info = bi,
		.mem_info = mi,
426
		.transaction = transaction,
427 428
	};

429
	return add_hist_entry(hists, &entry, al);
430 431
}

432 433 434 435 436 437 438
int64_t
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
{
	struct sort_entry *se;
	int64_t cmp = 0;

	list_for_each_entry(se, &hist_entry__sort_list, list) {
439
		cmp = se->se_cmp(left, right);
440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
		if (cmp)
			break;
	}

	return cmp;
}

int64_t
hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
{
	struct sort_entry *se;
	int64_t cmp = 0;

	list_for_each_entry(se, &hist_entry__sort_list, list) {
		int64_t (*f)(struct hist_entry *, struct hist_entry *);

456
		f = se->se_collapse ?: se->se_cmp;
457 458 459 460 461 462 463 464 465 466 467

		cmp = f(left, right);
		if (cmp)
			break;
	}

	return cmp;
}

void hist_entry__free(struct hist_entry *he)
{
468 469
	zfree(&he->branch_info);
	zfree(&he->mem_info);
470
	free_srcline(he->srcline);
471 472 473 474 475 476 477
	free(he);
}

/*
 * collapse the histogram
 */

478
static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
479 480
					 struct rb_root *root,
					 struct hist_entry *he)
481
{
482
	struct rb_node **p = &root->rb_node;
483 484 485 486 487 488
	struct rb_node *parent = NULL;
	struct hist_entry *iter;
	int64_t cmp;

	while (*p != NULL) {
		parent = *p;
489
		iter = rb_entry(parent, struct hist_entry, rb_node_in);
490 491 492 493

		cmp = hist_entry__collapse(iter, he);

		if (!cmp) {
494
			he_stat__add_stat(&iter->stat, &he->stat);
495

496
			if (symbol_conf.use_callchain) {
497 498 499
				callchain_cursor_reset(&callchain_cursor);
				callchain_merge(&callchain_cursor,
						iter->callchain,
500 501
						he->callchain);
			}
502
			hist_entry__free(he);
503
			return false;
504 505 506 507 508 509 510 511
		}

		if (cmp < 0)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

512 513
	rb_link_node(&he->rb_node_in, parent, p);
	rb_insert_color(&he->rb_node_in, root);
514
	return true;
515 516
}

517
static struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
518
{
519 520 521 522 523 524 525 526 527 528 529 530 531
	struct rb_root *root;

	pthread_mutex_lock(&hists->lock);

	root = hists->entries_in;
	if (++hists->entries_in > &hists->entries_in_array[1])
		hists->entries_in = &hists->entries_in_array[0];

	pthread_mutex_unlock(&hists->lock);

	return root;
}

532 533 534 535
static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
{
	hists__filter_entry_by_dso(hists, he);
	hists__filter_entry_by_thread(hists, he);
536
	hists__filter_entry_by_symbol(hists, he);
537 538
}

539
void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
540 541
{
	struct rb_root *root;
542 543 544
	struct rb_node *next;
	struct hist_entry *n;

545
	if (!sort__need_collapse)
546 547
		return;

548 549
	root = hists__get_rotate_entries_in(hists);
	next = rb_first(root);
550

551
	while (next) {
552 553
		if (session_done())
			break;
554 555
		n = rb_entry(next, struct hist_entry, rb_node_in);
		next = rb_next(&n->rb_node_in);
556

557
		rb_erase(&n->rb_node_in, root);
558 559 560 561 562 563 564 565
		if (hists__collapse_insert_entry(hists, &hists->entries_collapsed, n)) {
			/*
			 * If it wasn't combined with one of the entries already
			 * collapsed, we need to apply the filters that may have
			 * been set by, say, the hist_browser.
			 */
			hists__apply_filters(hists, n);
		}
566 567
		if (prog)
			ui_progress__update(prog, 1);
568
	}
569
}
570

571
/*
572
 * reverse the map, sort on period.
573 574
 */

575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
static int period_cmp(u64 period_a, u64 period_b)
{
	if (period_a > period_b)
		return 1;
	if (period_a < period_b)
		return -1;
	return 0;
}

static int hist_entry__sort_on_period(struct hist_entry *a,
				      struct hist_entry *b)
{
	int ret;
	int i, nr_members;
	struct perf_evsel *evsel;
	struct hist_entry *pair;
	u64 *periods_a, *periods_b;

	ret = period_cmp(a->stat.period, b->stat.period);
	if (ret || !symbol_conf.event_group)
		return ret;

	evsel = hists_to_evsel(a->hists);
	nr_members = evsel->nr_members;
	if (nr_members <= 1)
		return ret;

	periods_a = zalloc(sizeof(periods_a) * nr_members);
	periods_b = zalloc(sizeof(periods_b) * nr_members);

	if (!periods_a || !periods_b)
		goto out;

	list_for_each_entry(pair, &a->pairs.head, pairs.node) {
		evsel = hists_to_evsel(pair->hists);
		periods_a[perf_evsel__group_idx(evsel)] = pair->stat.period;
	}

	list_for_each_entry(pair, &b->pairs.head, pairs.node) {
		evsel = hists_to_evsel(pair->hists);
		periods_b[perf_evsel__group_idx(evsel)] = pair->stat.period;
	}

	for (i = 1; i < nr_members; i++) {
		ret = period_cmp(periods_a[i], periods_b[i]);
		if (ret)
			break;
	}

out:
	free(periods_a);
	free(periods_b);

	return ret;
}

631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
static void hists__reset_filter_stats(struct hists *hists)
{
	hists->nr_non_filtered_entries = 0;
	hists->stats.total_non_filtered_period = 0;
}

void hists__reset_stats(struct hists *hists)
{
	hists->nr_entries = 0;
	hists->stats.total_period = 0;

	hists__reset_filter_stats(hists);
}

static void hists__inc_filter_stats(struct hists *hists, struct hist_entry *h)
{
	hists->nr_non_filtered_entries++;
	hists->stats.total_non_filtered_period += h->stat.period;
}

void hists__inc_stats(struct hists *hists, struct hist_entry *h)
{
	if (!h->filtered)
		hists__inc_filter_stats(hists, h);

	hists->nr_entries++;
	hists->stats.total_period += h->stat.period;
}

660 661 662
static void __hists__insert_output_entry(struct rb_root *entries,
					 struct hist_entry *he,
					 u64 min_callchain_hits)
663
{
664
	struct rb_node **p = &entries->rb_node;
665 666 667
	struct rb_node *parent = NULL;
	struct hist_entry *iter;

668
	if (symbol_conf.use_callchain)
669
		callchain_param.sort(&he->sorted_chain, he->callchain,
670 671 672 673 674 675
				      min_callchain_hits, &callchain_param);

	while (*p != NULL) {
		parent = *p;
		iter = rb_entry(parent, struct hist_entry, rb_node);

676
		if (hist_entry__sort_on_period(he, iter) > 0)
677 678 679 680 681 682
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	rb_link_node(&he->rb_node, parent, p);
683
	rb_insert_color(&he->rb_node, entries);
684 685
}

686
void hists__output_resort(struct hists *hists)
687
{
688
	struct rb_root *root;
689 690 691 692
	struct rb_node *next;
	struct hist_entry *n;
	u64 min_callchain_hits;

693
	min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
694

695
	if (sort__need_collapse)
696 697 698 699 700 701
		root = &hists->entries_collapsed;
	else
		root = hists->entries_in;

	next = rb_first(root);
	hists->entries = RB_ROOT;
702

703
	hists__reset_stats(hists);
704
	hists__reset_col_len(hists);
705

706
	while (next) {
707 708
		n = rb_entry(next, struct hist_entry, rb_node_in);
		next = rb_next(&n->rb_node_in);
709

710
		__hists__insert_output_entry(&hists->entries, n, min_callchain_hits);
711
		hists__inc_stats(hists, n);
712 713 714

		if (!n->filtered)
			hists__calc_col_len(hists, n);
715
	}
716
}
717

718
static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
719 720 721 722 723 724
				       enum hist_filter filter)
{
	h->filtered &= ~(1 << filter);
	if (h->filtered)
		return;

725 726
	/* force fold unfiltered entry for simplicity */
	h->ms.unfolded = false;
727
	h->row_offset = 0;
728

729
	hists->stats.nr_non_filtered_samples += h->stat.nr_events;
730

731
	hists__inc_filter_stats(hists, h);
732
	hists__calc_col_len(hists, h);
733 734
}

735 736 737 738 739 740 741 742 743 744 745 746 747

static bool hists__filter_entry_by_dso(struct hists *hists,
				       struct hist_entry *he)
{
	if (hists->dso_filter != NULL &&
	    (he->ms.map == NULL || he->ms.map->dso != hists->dso_filter)) {
		he->filtered |= (1 << HIST_FILTER__DSO);
		return true;
	}

	return false;
}

748
void hists__filter_by_dso(struct hists *hists)
749 750 751
{
	struct rb_node *nd;

752
	hists->stats.nr_non_filtered_samples = 0;
753 754

	hists__reset_filter_stats(hists);
755
	hists__reset_col_len(hists);
756

757
	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
758 759 760 761 762
		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);

		if (symbol_conf.exclude_other && !h->parent)
			continue;

763
		if (hists__filter_entry_by_dso(hists, h))
764 765
			continue;

766
		hists__remove_entry_filter(hists, h, HIST_FILTER__DSO);
767 768 769
	}
}

770 771 772 773 774 775 776 777 778 779 780 781
static bool hists__filter_entry_by_thread(struct hists *hists,
					  struct hist_entry *he)
{
	if (hists->thread_filter != NULL &&
	    he->thread != hists->thread_filter) {
		he->filtered |= (1 << HIST_FILTER__THREAD);
		return true;
	}

	return false;
}

782
void hists__filter_by_thread(struct hists *hists)
783 784 785
{
	struct rb_node *nd;

786
	hists->stats.nr_non_filtered_samples = 0;
787 788

	hists__reset_filter_stats(hists);
789
	hists__reset_col_len(hists);
790

791
	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
792 793
		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);

794
		if (hists__filter_entry_by_thread(hists, h))
795
			continue;
796

797
		hists__remove_entry_filter(hists, h, HIST_FILTER__THREAD);
798 799
	}
}
800

801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
static bool hists__filter_entry_by_symbol(struct hists *hists,
					  struct hist_entry *he)
{
	if (hists->symbol_filter_str != NULL &&
	    (!he->ms.sym || strstr(he->ms.sym->name,
				   hists->symbol_filter_str) == NULL)) {
		he->filtered |= (1 << HIST_FILTER__SYMBOL);
		return true;
	}

	return false;
}

void hists__filter_by_symbol(struct hists *hists)
{
	struct rb_node *nd;

818
	hists->stats.nr_non_filtered_samples = 0;
819 820

	hists__reset_filter_stats(hists);
821 822 823 824 825 826 827 828 829 830 831 832
	hists__reset_col_len(hists);

	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);

		if (hists__filter_entry_by_symbol(hists, h))
			continue;

		hists__remove_entry_filter(hists, h, HIST_FILTER__SYMBOL);
	}
}

833 834 835 836 837 838
void events_stats__inc(struct events_stats *stats, u32 type)
{
	++stats->nr_events[0];
	++stats->nr_events[type];
}

839
void hists__inc_nr_events(struct hists *hists, u32 type)
840
{
841
	events_stats__inc(&hists->stats, type);
842
}
843

844 845 846
static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
						 struct hist_entry *pair)
{
847 848
	struct rb_root *root;
	struct rb_node **p;
849 850
	struct rb_node *parent = NULL;
	struct hist_entry *he;
851
	int64_t cmp;
852

853 854 855 856 857 858 859
	if (sort__need_collapse)
		root = &hists->entries_collapsed;
	else
		root = hists->entries_in;

	p = &root->rb_node;

860 861
	while (*p != NULL) {
		parent = *p;
862
		he = rb_entry(parent, struct hist_entry, rb_node_in);
863

864
		cmp = hist_entry__collapse(he, pair);
865 866 867 868 869 870 871 872 873 874 875 876

		if (!cmp)
			goto out;

		if (cmp < 0)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	he = hist_entry__new(pair);
	if (he) {
877 878
		memset(&he->stat, 0, sizeof(he->stat));
		he->hists = hists;
879 880
		rb_link_node(&he->rb_node_in, parent, p);
		rb_insert_color(&he->rb_node_in, root);
881
		hists__inc_stats(hists, he);
882
		he->dummy = true;
883 884 885 886 887
	}
out:
	return he;
}

888 889 890
static struct hist_entry *hists__find_entry(struct hists *hists,
					    struct hist_entry *he)
{
891 892 893 894 895 896
	struct rb_node *n;

	if (sort__need_collapse)
		n = hists->entries_collapsed.rb_node;
	else
		n = hists->entries_in->rb_node;
897 898

	while (n) {
899 900
		struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node_in);
		int64_t cmp = hist_entry__collapse(iter, he);
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917

		if (cmp < 0)
			n = n->rb_left;
		else if (cmp > 0)
			n = n->rb_right;
		else
			return iter;
	}

	return NULL;
}

/*
 * Look for pairs to link to the leader buckets (hist_entries):
 */
void hists__match(struct hists *leader, struct hists *other)
{
918
	struct rb_root *root;
919 920 921
	struct rb_node *nd;
	struct hist_entry *pos, *pair;

922 923 924 925 926 927 928
	if (sort__need_collapse)
		root = &leader->entries_collapsed;
	else
		root = leader->entries_in;

	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
		pos  = rb_entry(nd, struct hist_entry, rb_node_in);
929 930 931
		pair = hists__find_entry(other, pos);

		if (pair)
932
			hist_entry__add_pair(pair, pos);
933 934
	}
}
935 936 937 938 939 940 941 942

/*
 * Look for entries in the other hists that are not present in the leader, if
 * we find them, just add a dummy entry on the leader hists, with period=0,
 * nr_events=0, to serve as the list header.
 */
int hists__link(struct hists *leader, struct hists *other)
{
943
	struct rb_root *root;
944 945 946
	struct rb_node *nd;
	struct hist_entry *pos, *pair;

947 948 949 950 951 952 953
	if (sort__need_collapse)
		root = &other->entries_collapsed;
	else
		root = other->entries_in;

	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
		pos = rb_entry(nd, struct hist_entry, rb_node_in);
954 955 956 957 958

		if (!hist_entry__has_pairs(pos)) {
			pair = hists__add_dummy_entry(leader, pos);
			if (pair == NULL)
				return -1;
959
			hist_entry__add_pair(pos, pair);
960 961 962 963 964
		}
	}

	return 0;
}
965 966 967 968 969 970

u64 hists__total_period(struct hists *hists)
{
	return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
		hists->stats.total_period;
}
N
Namhyung Kim 已提交
971 972 973 974 975 976 977 978 979 980 981 982 983

int parse_filter_percentage(const struct option *opt __maybe_unused,
			    const char *arg, int unset __maybe_unused)
{
	if (!strcmp(arg, "relative"))
		symbol_conf.filter_relative = true;
	else if (!strcmp(arg, "absolute"))
		symbol_conf.filter_relative = false;
	else
		return -1;

	return 0;
}
984 985 986 987 988 989 990 991

int perf_hist_config(const char *var, const char *value)
{
	if (!strcmp(var, "hist.percentage"))
		return parse_filter_percentage(NULL, value, 0);

	return 0;
}