goto out_delete;
 
        if (dump_trace) {
-               event__print_totals();
+               perf_session__fprintf_nr_events(session, stdout);
                goto out_delete;
        }
 
 
                return -ENOMEM;
 
        hists->stats.total += data->period;
+       /*
+        * FIXME: add_event_total should be moved from here to
+        * perf_session__process_event so that the proper hist is passed to
+        * the event_op methods.
+        */
+       hists__inc_nr_events(hists, PERF_RECORD_SAMPLE);
        session->hists.stats.total += data->period;
        return 0;
 }
                goto out_delete;
 
        if (dump_trace) {
-               event__print_totals();
+               perf_session__fprintf_nr_events(session, stdout);
                goto out_delete;
        }
 
 
 #include "strlist.h"
 #include "thread.h"
 
+const char *event__name[] = {
+       [0]                      = "TOTAL",
+       [PERF_RECORD_MMAP]       = "MMAP",
+       [PERF_RECORD_LOST]       = "LOST",
+       [PERF_RECORD_COMM]       = "COMM",
+       [PERF_RECORD_EXIT]       = "EXIT",
+       [PERF_RECORD_THROTTLE]   = "THROTTLE",
+       [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE",
+       [PERF_RECORD_FORK]       = "FORK",
+       [PERF_RECORD_READ]       = "READ",
+       [PERF_RECORD_SAMPLE]     = "SAMPLE",
+       [PERF_RECORD_HEADER_ATTR]        = "ATTR",
+       [PERF_RECORD_HEADER_EVENT_TYPE]  = "EVENT_TYPE",
+       [PERF_RECORD_HEADER_TRACING_DATA]        = "TRACING_DATA",
+       [PERF_RECORD_HEADER_BUILD_ID]    = "BUILD_ID",
+};
+
 static pid_t event__synthesize_comm(pid_t pid, int full,
                                    event__handler_t process,
                                    struct perf_session *session)
 
                             struct addr_location *al, symbol_filter_t filter);
 int event__parse_sample(event_t *event, u64 type, struct sample_data *data);
 
+extern const char *event__name[];
+
 #endif /* __PERF_RECORD_H */
 
        pclose(file);
        return 0;
 }
+
+void hists__inc_nr_events(struct hists *self, u32 type)
+{
+       ++self->hists.stats.nr_events[0];
+       ++self->hists.stats.nr_events[type];
+}
+
+size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
+{
+       int i;
+       size_t ret = 0;
+
+       for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
+               if (!event__name[i])
+                       continue;
+               ret += fprintf(fp, "%10s events: %10d\n",
+                              event__name[i], self->stats.nr_events[i]);
+       }
+
+       return ret;
+}
 
 struct events_stats {
        u64 total;
        u64 lost;
+       u32 nr_events[PERF_RECORD_HEADER_MAX];
+       u32 nr_unknown_events;
 };
 
 struct hists {
 
 void hists__output_resort(struct hists *self);
 void hists__collapse_resort(struct hists *self);
+
+void hists__inc_nr_events(struct hists *self, u32 type);
+size_t hists__fprintf_nr_events(struct hists *self, FILE *fp);
+
 size_t hists__fprintf(struct hists *self, struct hists *pair,
                      bool show_displacement, FILE *fp);
 
 
        self->mmap_window = 32;
        self->cwd = NULL;
        self->cwdlen = 0;
-       self->unknown_events = 0;
        self->machines = RB_ROOT;
        self->repipe = repipe;
        INIT_LIST_HEAD(&self->ordered_samples.samples_head);
        }
 }
 
-static const char *event__name[] = {
-       [0]                      = "TOTAL",
-       [PERF_RECORD_MMAP]       = "MMAP",
-       [PERF_RECORD_LOST]       = "LOST",
-       [PERF_RECORD_COMM]       = "COMM",
-       [PERF_RECORD_EXIT]       = "EXIT",
-       [PERF_RECORD_THROTTLE]   = "THROTTLE",
-       [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE",
-       [PERF_RECORD_FORK]       = "FORK",
-       [PERF_RECORD_READ]       = "READ",
-       [PERF_RECORD_SAMPLE]     = "SAMPLE",
-       [PERF_RECORD_HEADER_ATTR]        = "ATTR",
-       [PERF_RECORD_HEADER_EVENT_TYPE]  = "EVENT_TYPE",
-       [PERF_RECORD_HEADER_TRACING_DATA]        = "TRACING_DATA",
-       [PERF_RECORD_HEADER_BUILD_ID]    = "BUILD_ID",
-};
-
-unsigned long event__total[PERF_RECORD_HEADER_MAX];
-
-void event__print_totals(void)
-{
-       int i;
-       for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
-               if (!event__name[i])
-                       continue;
-               pr_info("%10s events: %10ld\n",
-                       event__name[i], event__total[i]);
-       }
-}
-
 void mem_bswap_64(void *src, int byte_size)
 {
        u64 *m = src;
                dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
                            offset + head, event->header.size,
                            event__name[event->header.type]);
-               ++event__total[0];
-               ++event__total[event->header.type];
+               hists__inc_nr_events(self, event->header.type);
        }
 
        if (self->header.needs_swap && event__swap_ops[event->header.type])
        case PERF_RECORD_FINISHED_ROUND:
                return ops->finished_round(event, self, ops);
        default:
-               self->unknown_events++;
+               ++self->hists.stats.nr_unknown_events;
                return -1;
        }
 }
 
        struct machine          host_machine;
        struct rb_root          machines;
        struct rb_root          hists_tree;
-       unsigned long           event_total[PERF_RECORD_MAX];
-       unsigned long           unknown_events;
        /*
         * FIXME: should point to the first entry in hists_tree and
         *        be a hists instance. Right now its only 'report'
 {
        return machines__fprintf_dsos_buildid(&self->machines, fp, with_hits);
 }
+
+static inline
+size_t perf_session__fprintf_nr_events(struct perf_session *self, FILE *fp)
+{
+       return hists__fprintf_nr_events(&self->hists, fp);
+}
 #endif /* __PERF_SESSION_H */