Commit d890a98c authored by Hari Bathini's avatar Hari Bathini Committed by Arnaldo Carvalho de Melo

perf tools: Add 'cgroup_id' sort order keyword

This patch introduces a cgroup identifier entry field in perf report to
identify or distinguish data of different cgroups. It uses the device
number and inode number of cgroup namespace, included in perf data with
the new PERF_RECORD_NAMESPACES event, as cgroup identifier.

With the assumption that each container is created with it's own cgroup
namespace,  this allows assessment/analysis of multiple containers at
once.

A simple test for this would be to clone a few processes passing
SIGCHILD & CLONE_NEWCROUP flags to each of them, execute shell and run
different workloads  on each of those contexts,  while running perf
record command with --namespaces option.

Shown below is the output of perf report, sorted with cgroup identifier,
on perf.data generated with the above test scenario, clearly indicating
one context's considerable use of kernel memory in comparison with
others:

	$ perf report -s cgroup_id,sample --stdio
	#
	# Total Lost Samples: 0
	#
	# Samples: 5K of event 'kmem:kmalloc'
	# Event count (approx.): 5965
	#
	# Overhead  cgroup id (dev/inode)       Samples
	# ........  .....................  ............
	#
	    81.27%  3/0xeffffffb                   4848
	    16.24%  3/0xf00000d0                    969
	     1.16%  3/0xf00000ce                     69
	     0.82%  3/0xf00000cf                     49
	     0.50%  0/0x0                            30

While this is a start, there is further scope of improving this. For
example, instead of cgroup namespace's device and inode numbers, dev
and inode numbers of some or all namespaces may be used to distinguish
which processes are running in a given container context.

Also, scripts to map device and inode info to containers sounds
plausible for better tracing of containers.
Signed-off-by: default avatarHari Bathini <hbathini@linux.vnet.ibm.com>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Ananth N Mavinakayanahalli <ananth@linux.vnet.ibm.com>
Cc: Aravinda Prasad <aravinda@linux.vnet.ibm.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Sargun Dhillon <sargun@sargun.me>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/148891933338.25309.756882900782042645.stgit@hbathini.in.ibm.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 96a44bbc
...@@ -72,7 +72,8 @@ OPTIONS ...@@ -72,7 +72,8 @@ OPTIONS
--sort=:: --sort=::
Sort histogram entries by given key(s) - multiple keys can be specified Sort histogram entries by given key(s) - multiple keys can be specified
in CSV format. Following sort keys are available: in CSV format. Following sort keys are available:
pid, comm, dso, symbol, parent, cpu, socket, srcline, weight, local_weight. pid, comm, dso, symbol, parent, cpu, socket, srcline, weight,
local_weight, cgroup_id.
Each key has following meaning: Each key has following meaning:
...@@ -92,6 +93,7 @@ OPTIONS ...@@ -92,6 +93,7 @@ OPTIONS
- weight: Event specific weight, e.g. memory latency or transaction - weight: Event specific weight, e.g. memory latency or transaction
abort cost. This is the global weight. abort cost. This is the global weight.
- local_weight: Local weight version of the weight above. - local_weight: Local weight version of the weight above.
- cgroup_id: ID derived from cgroup namespace device and inode numbers.
- transaction: Transaction abort flags. - transaction: Transaction abort flags.
- overhead: Overhead percentage of sample - overhead: Overhead percentage of sample
- overhead_sys: Overhead percentage of sample running in system mode - overhead_sys: Overhead percentage of sample running in system mode
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "hist.h" #include "hist.h"
#include "map.h" #include "map.h"
#include "session.h" #include "session.h"
#include "namespaces.h"
#include "sort.h" #include "sort.h"
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
...@@ -169,6 +170,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h) ...@@ -169,6 +170,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO); hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
} }
hists__new_col_len(hists, HISTC_CGROUP_ID, 20);
hists__new_col_len(hists, HISTC_CPU, 3); hists__new_col_len(hists, HISTC_CPU, 3);
hists__new_col_len(hists, HISTC_SOCKET, 6); hists__new_col_len(hists, HISTC_SOCKET, 6);
hists__new_col_len(hists, HISTC_MEM_LOCKED, 6); hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
...@@ -574,9 +576,14 @@ __hists__add_entry(struct hists *hists, ...@@ -574,9 +576,14 @@ __hists__add_entry(struct hists *hists,
bool sample_self, bool sample_self,
struct hist_entry_ops *ops) struct hist_entry_ops *ops)
{ {
struct namespaces *ns = thread__namespaces(al->thread);
struct hist_entry entry = { struct hist_entry entry = {
.thread = al->thread, .thread = al->thread,
.comm = thread__comm(al->thread), .comm = thread__comm(al->thread),
.cgroup_id = {
.dev = ns ? ns->link_info[CGROUP_NS_INDEX].dev : 0,
.ino = ns ? ns->link_info[CGROUP_NS_INDEX].ino : 0,
},
.ms = { .ms = {
.map = al->map, .map = al->map,
.sym = al->sym, .sym = al->sym,
......
...@@ -30,6 +30,7 @@ enum hist_column { ...@@ -30,6 +30,7 @@ enum hist_column {
HISTC_DSO, HISTC_DSO,
HISTC_THREAD, HISTC_THREAD,
HISTC_COMM, HISTC_COMM,
HISTC_CGROUP_ID,
HISTC_PARENT, HISTC_PARENT,
HISTC_CPU, HISTC_CPU,
HISTC_SOCKET, HISTC_SOCKET,
......
...@@ -536,6 +536,46 @@ struct sort_entry sort_cpu = { ...@@ -536,6 +536,46 @@ struct sort_entry sort_cpu = {
.se_width_idx = HISTC_CPU, .se_width_idx = HISTC_CPU,
}; };
/* --sort cgroup_id */
static int64_t _sort__cgroup_dev_cmp(u64 left_dev, u64 right_dev)
{
return (int64_t)(right_dev - left_dev);
}
static int64_t _sort__cgroup_inode_cmp(u64 left_ino, u64 right_ino)
{
return (int64_t)(right_ino - left_ino);
}
static int64_t
sort__cgroup_id_cmp(struct hist_entry *left, struct hist_entry *right)
{
int64_t ret;
ret = _sort__cgroup_dev_cmp(right->cgroup_id.dev, left->cgroup_id.dev);
if (ret != 0)
return ret;
return _sort__cgroup_inode_cmp(right->cgroup_id.ino,
left->cgroup_id.ino);
}
static int hist_entry__cgroup_id_snprintf(struct hist_entry *he,
char *bf, size_t size,
unsigned int width __maybe_unused)
{
return repsep_snprintf(bf, size, "%lu/0x%lx", he->cgroup_id.dev,
he->cgroup_id.ino);
}
struct sort_entry sort_cgroup_id = {
.se_header = "cgroup id (dev/inode)",
.se_cmp = sort__cgroup_id_cmp,
.se_snprintf = hist_entry__cgroup_id_snprintf,
.se_width_idx = HISTC_CGROUP_ID,
};
/* --sort socket */ /* --sort socket */
static int64_t static int64_t
...@@ -1464,6 +1504,7 @@ static struct sort_dimension common_sort_dimensions[] = { ...@@ -1464,6 +1504,7 @@ static struct sort_dimension common_sort_dimensions[] = {
DIM(SORT_TRANSACTION, "transaction", sort_transaction), DIM(SORT_TRANSACTION, "transaction", sort_transaction),
DIM(SORT_TRACE, "trace", sort_trace), DIM(SORT_TRACE, "trace", sort_trace),
DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size), DIM(SORT_SYM_SIZE, "symbol_size", sort_sym_size),
DIM(SORT_CGROUP_ID, "cgroup_id", sort_cgroup_id),
}; };
#undef DIM #undef DIM
......
...@@ -54,6 +54,11 @@ struct he_stat { ...@@ -54,6 +54,11 @@ struct he_stat {
u32 nr_events; u32 nr_events;
}; };
struct namespace_id {
u64 dev;
u64 ino;
};
struct hist_entry_diff { struct hist_entry_diff {
bool computed; bool computed;
union { union {
...@@ -91,6 +96,7 @@ struct hist_entry { ...@@ -91,6 +96,7 @@ struct hist_entry {
struct map_symbol ms; struct map_symbol ms;
struct thread *thread; struct thread *thread;
struct comm *comm; struct comm *comm;
struct namespace_id cgroup_id;
u64 ip; u64 ip;
u64 transaction; u64 transaction;
s32 socket; s32 socket;
...@@ -212,6 +218,7 @@ enum sort_type { ...@@ -212,6 +218,7 @@ enum sort_type {
SORT_TRANSACTION, SORT_TRANSACTION,
SORT_TRACE, SORT_TRACE,
SORT_SYM_SIZE, SORT_SYM_SIZE,
SORT_CGROUP_ID,
/* branch stack specific sort keys */ /* branch stack specific sort keys */
__SORT_BRANCH_STACK, __SORT_BRANCH_STACK,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment