]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - tools/perf/util/session.c
perf session: Keep file mmaped instead of malloc/memcpy
[mv-sheeva.git] / tools / perf / util / session.c
index 9c806ab565eaf997c2c9c0adb68d4dc97f2a01cc..c989583141029d3a42c699766e9abd28fb87b39d 100644 (file)
@@ -101,7 +101,15 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc
        INIT_LIST_HEAD(&self->dead_threads);
        self->hists_tree = RB_ROOT;
        self->last_match = NULL;
-       self->mmap_window = 32;
+       /*
+        * On 64bit we can mmap the data file in one go. No need for tiny mmap
+        * slices. On 32bit we use 32MB.
+        */
+#if BITS_PER_LONG == 64
+       self->mmap_window = ULLONG_MAX;
+#else
+       self->mmap_window = 32 * 1024 * 1024ULL;
+#endif
        self->machines = RB_ROOT;
        self->repipe = repipe;
        INIT_LIST_HEAD(&self->ordered_samples.samples);
@@ -410,7 +418,6 @@ static void flush_sample_queue(struct perf_session *s,
 
                os->last_flush = iter->timestamp;
                list_del(&iter->list);
-               free(iter->event);
                free(iter);
        }
 
@@ -523,7 +530,6 @@ static int queue_sample_event(event_t *event, struct sample_data *data,
        u64 timestamp = data->time;
        struct sample_queue *new;
 
-
        if (timestamp < s->ordered_samples.last_flush) {
                printf("Warning: Timestamp below last timeslice flush\n");
                return -EINVAL;
@@ -534,14 +540,7 @@ static int queue_sample_event(event_t *event, struct sample_data *data,
                return -ENOMEM;
 
        new->timestamp = timestamp;
-
-       new->event = malloc(event->header.size);
-       if (!new->event) {
-               free(new);
-               return -ENOMEM;
-       }
-
-       memcpy(new->event, event, event->header.size);
+       new->event = event;
 
        __queue_sample_event(new, s);
 
@@ -738,17 +737,13 @@ int __perf_session__process_events(struct perf_session *session,
                                   u64 data_offset, u64 data_size,
                                   u64 file_size, struct perf_event_ops *ops)
 {
-       u64 head, page_offset, file_offset, file_pos;
-       int err, mmap_prot, mmap_flags;
+       u64 head, page_offset, file_offset, file_pos, progress_next;
+       int err, mmap_prot, mmap_flags, map_idx = 0;
        struct ui_progress *progress;
-       size_t  page_size;
+       size_t  page_size, mmap_size;
+       char *buf, *mmaps[8];
        event_t *event;
        uint32_t size;
-       char *buf;
-
-       progress = ui_progress__new("Processing events...", session->size);
-       if (progress == NULL)
-               return -1;
 
        perf_event_ops__fill_defaults(ops);
 
@@ -761,6 +756,17 @@ int __perf_session__process_events(struct perf_session *session,
        if (data_offset + data_size < file_size)
                file_size = data_offset + data_size;
 
+       progress_next = file_size / 16;
+       progress = ui_progress__new("Processing events...", file_size);
+       if (progress == NULL)
+               return -1;
+
+       mmap_size = session->mmap_window;
+       if (mmap_size > file_size)
+               mmap_size = file_size;
+
+       memset(mmaps, 0, sizeof(mmaps));
+
        mmap_prot  = PROT_READ;
        mmap_flags = MAP_SHARED;
 
@@ -769,15 +775,16 @@ int __perf_session__process_events(struct perf_session *session,
                mmap_flags = MAP_PRIVATE;
        }
 remap:
-       buf = mmap(NULL, page_size * session->mmap_window, mmap_prot,
-                  mmap_flags, session->fd, file_offset);
+       buf = mmap(NULL, mmap_size, mmap_prot, mmap_flags, session->fd,
+                  file_offset);
        if (buf == MAP_FAILED) {
                pr_err("failed to mmap file\n");
                err = -errno;
                goto out_err;
        }
+       mmaps[map_idx] = buf;
+       map_idx = (map_idx + 1) & (ARRAY_SIZE(mmaps) - 1);
        file_pos = file_offset + head;
-       ui_progress__update(progress, file_offset);
 
 more:
        event = (event_t *)(buf + head);
@@ -788,11 +795,11 @@ more:
        if (size == 0)
                size = 8;
 
-       if (head + event->header.size >= page_size * session->mmap_window) {
-               int munmap_ret;
-
-               munmap_ret = munmap(buf, page_size * session->mmap_window);
-               assert(munmap_ret == 0);
+       if (head + event->header.size >= mmap_size) {
+               if (mmaps[map_idx]) {
+                       munmap(mmaps[map_idx], mmap_size);
+                       mmaps[map_idx] = NULL;
+               }
 
                page_offset = page_size * (head / page_size);
                file_offset += page_offset;
@@ -823,6 +830,11 @@ more:
        head += size;
        file_pos += size;
 
+       if (file_pos >= progress_next) {
+               progress_next += file_size / 16;
+               ui_progress__update(progress, file_pos);
+       }
+
        if (file_pos < file_size)
                goto more;