Skip to content

Commit

Permalink
perf record: Allow to limit number of reported perf.data files
Browse files Browse the repository at this point in the history
When doing long term recording and waiting for some event to snapshot
on, we often only care about the last minute or so.

The --switch-output command line option supports rotating the perf.data
file when the size exceeds a threshold. But the disk would still be
filled with unnecessary old files.

Add a new option to only keep a number of rotated files, so that the
disk space usage can be limited.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Jiri Olsa <jolsa@kernel.org>
LPU-Reference: 20190314225002.30108-3-andi@firstfloor.org
Link: https://lkml.kernel.org/n/tip-y5u2lik0ragt4vlktz6qc9ks@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Andi Kleen authored and Arnaldo Carvalho de Melo committed Mar 19, 2019
1 parent 6f40b2a commit 03724b2
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 8 deletions.
4 changes: 4 additions & 0 deletions tools/perf/Documentation/perf-record.txt
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,10 @@ overhead. You can still switch them on with:

--switch-output --no-no-buildid --no-no-buildid-cache

--switch-max-files=N::

When rotating perf.data with --switch-output, only keep N files.

--dry-run::
Parse options then exit. --dry-run can be used to detect errors in cmdline
options.
Expand Down
30 changes: 29 additions & 1 deletion tools/perf/builtin-record.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ struct switch_output {
unsigned long time;
const char *str;
bool set;
char **filenames;
int num_files;
int cur_file;
};

struct record {
Expand Down Expand Up @@ -892,6 +895,7 @@ record__switch_output(struct record *rec, bool at_exit)
{
struct perf_data *data = &rec->data;
int fd, err;
char *new_filename;

/* Same Size: "2015122520103046"*/
char timestamp[] = "InvalidTimestamp";
Expand All @@ -912,7 +916,7 @@ record__switch_output(struct record *rec, bool at_exit)

fd = perf_data__switch(data, timestamp,
rec->session->header.data_offset,
at_exit);
at_exit, &new_filename);
if (fd >= 0 && !at_exit) {
rec->bytes_written = 0;
rec->session->header.data_size = 0;
Expand All @@ -922,6 +926,21 @@ record__switch_output(struct record *rec, bool at_exit)
fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
data->path, timestamp);

if (rec->switch_output.num_files) {
int n = rec->switch_output.cur_file + 1;

if (n >= rec->switch_output.num_files)
n = 0;
rec->switch_output.cur_file = n;
if (rec->switch_output.filenames[n]) {
remove(rec->switch_output.filenames[n]);
free(rec->switch_output.filenames[n]);
}
rec->switch_output.filenames[n] = new_filename;
} else {
free(new_filename);
}

/* Output tracking events */
if (!at_exit) {
record__synthesize(rec, false);
Expand Down Expand Up @@ -1973,6 +1992,8 @@ static struct option __record_options[] = {
&record.switch_output.set, "signal,size,time",
"Switch output when receive SIGUSR2 or cross size,time threshold",
"signal"),
OPT_INTEGER(0, "switch-max-files", &record.switch_output.num_files,
"Limit number of switch output generated files"),
OPT_BOOLEAN(0, "dry-run", &dry_run,
"Parse options then exit"),
#ifdef HAVE_AIO_SUPPORT
Expand Down Expand Up @@ -2059,6 +2080,13 @@ int cmd_record(int argc, const char **argv)
alarm(rec->switch_output.time);
}

if (rec->switch_output.num_files) {
rec->switch_output.filenames = calloc(sizeof(char *),
rec->switch_output.num_files);
if (!rec->switch_output.filenames)
return -EINVAL;
}

/*
* Allow aliases to facilitate the lookup of symbols for address
* filters. Refer to auxtrace_parse_filters().
Expand Down
11 changes: 5 additions & 6 deletions tools/perf/util/data.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,25 +361,25 @@ ssize_t perf_data__write(struct perf_data *data,

int perf_data__switch(struct perf_data *data,
const char *postfix,
size_t pos, bool at_exit)
size_t pos, bool at_exit,
char **new_filepath)
{
char *new_filepath;
int ret;

if (check_pipe(data))
return -EINVAL;
if (perf_data__is_read(data))
return -EINVAL;

if (asprintf(&new_filepath, "%s.%s", data->path, postfix) < 0)
if (asprintf(new_filepath, "%s.%s", data->path, postfix) < 0)
return -ENOMEM;

/*
* Only fire a warning, don't return error, continue fill
* original file.
*/
if (rename(data->path, new_filepath))
pr_warning("Failed to rename %s to %s\n", data->path, new_filepath);
if (rename(data->path, *new_filepath))
pr_warning("Failed to rename %s to %s\n", data->path, *new_filepath);

if (!at_exit) {
close(data->file.fd);
Expand All @@ -396,7 +396,6 @@ int perf_data__switch(struct perf_data *data,
}
ret = data->file.fd;
out:
free(new_filepath);
return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion tools/perf/util/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
*/
int perf_data__switch(struct perf_data *data,
const char *postfix,
size_t pos, bool at_exit);
size_t pos, bool at_exit, char **new_filepath);

int perf_data__create_dir(struct perf_data *data, int nr);
int perf_data__open_dir(struct perf_data *data);
Expand Down

0 comments on commit 03724b2

Please sign in to comment.