perf: Minimize the sampling of perf itself
authorBarret Rhoden <brho@cs.berkeley.edu>
Wed, 15 Jun 2016 15:10:30 +0000 (11:10 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 17 Jun 2016 16:17:54 +0000 (12:17 -0400)
The perf events fire as soon as you submit them to the kernel.  We can
control whether or not we gather the actual samples (i.e. backtraces) for
perf record.  This will minimize the impact of perf on the trace, as well
as just be a little cleaner.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tools/profile/perf/perf.c
tools/profile/perf/perf_core.c
tools/profile/perf/perf_core.h

index de5e774..8e02d06 100644 (file)
@@ -318,13 +318,17 @@ static int perf_record(struct perf_cmd *cmd, int argc, char *argv[])
        collect_argp(cmd, argc, argv, children, &opts);
        opts.sampling = TRUE;
 
+       /* Once a perf event is submitted, it'll start counting and firing the IRQ.
+        * However, we can control whether or not the samples are collected. */
        submit_events(&opts);
+       perf_start_sampling(pctx);
        run_process_and_wait(opts.cmd_argc, opts.cmd_argv, &opts.cores);
+       perf_stop_sampling(pctx);
        if (opts.verbose)
                perf_context_show_values(pctx, stdout);
-       /* Flush the profiler per-CPU trace data into the main queue, so that
-        * it will be available for read. */
-       perf_flush_context_traces(pctx);
+       /* The events are still counting and firing IRQs.  Let's be nice and turn
+        * them off to minimize our impact. */
+       perf_stop_events(pctx);
        /* Generate the Linux perf file format with the traces which have been
         * created during this operation. */
        perf_convert_trace_data(cctx, perf_cfg.kpdata_file, opts.outfile);
index 88e8e1c..ae70a5d 100644 (file)
@@ -517,27 +517,6 @@ static void perf_close_event(int perf_fd, int ped)
        xpwrite(perf_fd, cmdbuf, wptr - cmdbuf, 0);
 }
 
-static void perf_enable_sampling(int kpctl_fd)
-{
-       static const char * const enable_str = "start";
-
-       xwrite(kpctl_fd, enable_str, strlen(enable_str));
-}
-
-static void perf_disable_sampling(int kpctl_fd)
-{
-       static const char * const disable_str = "stop";
-
-       xwrite(kpctl_fd, disable_str, strlen(disable_str));
-}
-
-static void perf_flush_sampling(int kpctl_fd)
-{
-       static const char * const flush_str = "flush";
-
-       xwrite(kpctl_fd, flush_str, strlen(flush_str));
-}
-
 struct perf_context *perf_create_context(const struct perf_context_config *cfg)
 {
        struct perf_context *pctx = xzmalloc(sizeof(struct perf_context));
@@ -545,7 +524,6 @@ struct perf_context *perf_create_context(const struct perf_context_config *cfg)
        pctx->perf_fd = xopen(cfg->perf_file, O_RDWR, 0);
        pctx->kpctl_fd = xopen(cfg->kpctl_file, O_RDWR, 0);
        perf_get_arch_info(pctx->perf_fd, &pctx->pai);
-       perf_enable_sampling(pctx->kpctl_fd);
 
        return pctx;
 }
@@ -557,11 +535,6 @@ void perf_free_context(struct perf_context *pctx)
        free(pctx);
 }
 
-void perf_flush_context_traces(struct perf_context *pctx)
-{
-       perf_flush_sampling(pctx->kpctl_fd);
-}
-
 void perf_context_event_submit(struct perf_context *pctx,
                                                           const struct core_set *cores,
                                                           const struct perf_eventsel *sel)
@@ -583,6 +556,26 @@ void perf_context_event_submit(struct perf_context *pctx,
        }
 }
 
+void perf_stop_events(struct perf_context *pctx)
+{
+       for (int i = 0; i < pctx->event_count; i++)
+               perf_close_event(pctx->perf_fd, pctx->events[i].ped);
+}
+
+void perf_start_sampling(struct perf_context *pctx)
+{
+       static const char * const enable_str = "start";
+
+       xwrite(pctx->kpctl_fd, enable_str, strlen(enable_str));
+}
+
+void perf_stop_sampling(struct perf_context *pctx)
+{
+       static const char * const disable_str = "stop";
+
+       xwrite(pctx->kpctl_fd, disable_str, strlen(disable_str));
+}
+
 void perf_context_show_values(struct perf_context *pctx, FILE *file)
 {
        for (int i = 0; i < pctx->event_count; i++) {
index a3590f6..7848697 100644 (file)
@@ -60,10 +60,12 @@ void perf_finalize(void);
 struct perf_eventsel *perf_parse_event(const char *str);
 struct perf_context *perf_create_context(const struct perf_context_config *cfg);
 void perf_free_context(struct perf_context *pctx);
-void perf_flush_context_traces(struct perf_context *pctx);
 void perf_context_event_submit(struct perf_context *pctx,
                                                           const struct core_set *cores,
                                                           const struct perf_eventsel *sel);
+void perf_stop_events(struct perf_context *pctx);
+void perf_start_sampling(struct perf_context *pctx);
+void perf_stop_sampling(struct perf_context *pctx);
 void perf_context_show_values(struct perf_context *pctx, FILE *file);
 void perf_show_events(const char *rx, FILE *file);
 void perf_convert_trace_data(struct perfconv_context *cctx, const char *input,