]> git.neil.brown.name Git - edlib.git/commitdiff
Introduce memory usage tracking.
authorNeilBrown <neil@brown.name>
Mon, 2 Mar 2020 22:00:41 +0000 (09:00 +1100)
committerNeilBrown <neil@brown.name>
Mon, 2 Mar 2020 22:00:41 +0000 (09:00 +1100)
Currently we only track how much memory is used for marks,
but this is mainly to introduce infrastructure.
Subsequent patches will add more pools for tracking memory usage.

Signed-off-by: NeilBrown <neil@brown.name>
core-editor.c
core-mark.c
core-misc.c
internal.h
misc.h

index f759c6e727f6f9f4f805797a444d38f9faad1504..c1f0088034f23bff8eef068192c6e73242df629c 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "core.h"
 #include "misc.h"
+#include "internal.h"
 
 static struct map *ed_map safe;
 struct ed_info {
@@ -244,7 +245,7 @@ DEF_CMD(editor_clean_up)
        while (ei->mark_free_list) {
                struct mark *m = ei->mark_free_list;
                ei->mark_free_list = (struct mark*)m->all.next;
-               free(m);
+               __mark_free(m);
        }
        while (ei->store) {
                struct store *s = ei->store;
@@ -382,7 +383,7 @@ void editor_delayed_mark_free(struct mark *m safe)
        struct ed_info *ei = p ? p->data : NULL;
 
        if (!ei) {
-               free(m);
+               __mark_free(m);
                return;
        }
        ASSERT(ei->magic==0x4321765498765432UL);
index 237b9c46426189a15044ad242f38c22033c7ba15..d1ca7b3dac3e66554bcbb0753fef6c64106a5f3c 100644 (file)
@@ -70,6 +70,9 @@
 
 #include "core.h"
 #include "internal.h"
+#include "misc.h"
+
+static MEMPOOL(mark);
 
 /* seq numbers added to the end are given a gap of 128.
  * seq numbers at other locations are placed at mean of before and after.
@@ -113,8 +116,13 @@ static void point_free(struct mark *p safe)
        struct point_links *lnk = safe_cast p->mdata;
        for (i = 0; i < lnk->size; i++)
                tlist_del_init(&lnk->lists[i]);
-       free(lnk);
-       p->mdata = NULL;
+       unalloc_buf(p->mdata, sizeof(*lnk) + lnk->size * sizeof(lnk->lists[0]),
+                   mark);
+}
+
+void __mark_free(struct mark *m)
+{
+       unalloc(m, mark);
 }
 
 void mark_free(struct mark *m)
@@ -171,7 +179,7 @@ struct mark *do_mark_at_point(struct mark *pt safe, int view)
                return NULL;
        lnk = safe_cast pt->mdata;
 
-       ret = calloc(1, sizeof(*ret));
+       alloc(ret, mark);
 
        dup_mark(pt, ret);
        ret->viewnum = view;
@@ -191,9 +199,12 @@ struct mark *safe point_dup(struct mark *p safe)
 {
        int i;
        struct point_links *old = safe_cast p->mdata;
-       struct mark *ret = calloc(1, sizeof(*ret));
-       struct point_links *lnk = malloc(sizeof(*lnk) +
-                                        old->size * sizeof(lnk->lists[0]));
+       struct mark *ret;
+       struct point_links *lnk;
+
+       alloc(ret, mark);
+       lnk = alloc_buf(sizeof(*lnk) + old->size * sizeof(lnk->lists[0]),
+                       mark);
 
        dup_mark(p, ret);
        ret->viewnum = MARK_POINT;
@@ -216,9 +227,10 @@ void points_resize(struct doc *d safe)
        tlist_for_each_entry(p, &d->points, view) {
                int i;
                struct point_links *old = safe_cast p->mdata;
-               struct point_links *new = malloc(sizeof(*new) +
-                                                d->nviews *
-                                                sizeof(new->lists[0]));
+               struct point_links *new = alloc_buf(sizeof(*new) +
+                                                   d->nviews *
+                                                   sizeof(new->lists[0]),
+                                                   mark);
                new->pt = p;
                new->size = d->nviews;
                new->moved = old->moved;
@@ -247,7 +259,7 @@ struct mark *safe mark_dup(struct mark *m safe)
 {
        struct mark *ret;
 
-       ret = calloc(1, sizeof(*ret));
+       alloc(ret, mark);
        dup_mark(m, ret);
        ret->viewnum = MARK_UNGROUPED;
        INIT_TLIST_HEAD(&ret->view, GRP_MARK);
@@ -261,7 +273,7 @@ struct mark *safe mark_dup_view(struct mark *m safe)
        if (m->viewnum == MARK_POINT)
                return point_dup(m);
 
-       ret = calloc(1, sizeof(*ret));
+       alloc(ret, mark);
        dup_mark(m, ret);
        if (m->viewnum == MARK_POINT) abort();
        ret->viewnum = m->viewnum;
@@ -387,16 +399,17 @@ struct mark *doc_new_mark(struct doc *d safe, int view, struct pane *owner)
                /* Erroneous call, or race with document closing down */
                return NULL;
        }
-       ret = calloc(1, sizeof(*ret));
+       alloc(ret, mark);
        INIT_HLIST_NODE(&ret->all);
        INIT_TLIST_HEAD(&ret->view, GRP_MARK);
        ret->viewnum = view;
        hlist_add_head(&ret->all, &d->marks);
 
        if (view == MARK_POINT) {
-               struct point_links *lnk = malloc(sizeof(*lnk) +
-                                                d->nviews *
-                                                sizeof(lnk->lists[0]));
+               struct point_links *lnk = alloc_buf(sizeof(*lnk) +
+                                                   d->nviews *
+                                                   sizeof(lnk->lists[0]),
+                                                   mark);
                int i;
 
                lnk->size = d->nviews;
index 5cc104c62b3fe94132557620a77795fab6fd0dbb..7da153279f56f2d805e8b7089a1a7c01a3b7fb25 100644 (file)
@@ -14,7 +14,7 @@
 #include <unistd.h>
 
 #include "safe.h"
-
+#include "list.h"
 #include "misc.h"
 
 void buf_init(struct buf *b safe)
@@ -78,6 +78,7 @@ static FILE *dump_file;
 static void dump_key_hash(void);
 static void dump_count_hash(void);
 static void stat_dump(void);
+static void dump_mem(void);
 
 static char *tnames[] = {
        [TIME_KEY]     = "KEY",
@@ -151,6 +152,7 @@ static void stat_dump(void)
        dump_key_hash();
        dump_count_hash();
        fprintf(dump_file, "\n");
+       dump_mem();
        fflush(dump_file);
 }
 
@@ -329,3 +331,40 @@ void stat_free(void)
        hash_free(khashtab);
        stats_enabled = 0;
 }
+
+static LIST_HEAD(mem_pools);
+
+void *safe __alloc(struct mempool *pool safe, int size, int zero)
+{
+       void *ret = malloc(size);
+
+       if (zero)
+               memset(ret, 0, size);
+       pool->bytes += size;
+       pool->allocations += 1;
+       if (pool->bytes > pool->max_bytes)
+               pool->max_bytes = pool->bytes;
+       if (list_empty(&pool->linkage))
+               list_add(&pool->linkage, &mem_pools);
+       return ret;
+}
+
+void __unalloc(struct mempool *pool safe, void *obj, int size)
+{
+       if (obj) {
+               pool->bytes -= size;
+               pool->allocations -= 1;
+               free(obj);
+       }
+}
+
+static void dump_mem(void)
+{
+       struct mempool *p;
+
+       fprintf(dump_file, "mem:");
+       list_for_each_entry(p, &mem_pools, linkage)
+               fprintf(dump_file, " %s:%ld(%ld):%ld",
+                       p->name, p->bytes, p->max_bytes, p->allocations);
+       fprintf(dump_file, "\n");
+}
index 85c6d84063dc2677da6bb82bb1eb595cd96f2ab6..1b88657688bb997ed3e30e639787d6aed01de634 100644 (file)
@@ -15,3 +15,4 @@ struct mark *do_vmark_first(struct doc *d safe, int view, struct pane *owner saf
 struct mark *do_vmark_last(struct doc *d safe, int view, struct pane *owner safe);
 struct mark *do_vmark_at_point(struct doc *d safe, struct mark *pt safe, int view, struct pane *owner safe);
 struct mark *do_vmark_at_or_before(struct doc *d safe, struct mark *m safe, int view, struct pane *owner);
+void __mark_free(struct mark *m);
diff --git a/misc.h b/misc.h
index 65be4a94027bc5d60cd6a3c766f330584cff4234..4dafd54ff609e9174fb16799307efc5b544a34ee 100644 (file)
--- a/misc.h
+++ b/misc.h
@@ -46,3 +46,36 @@ void time_stop_key(const char *key safe);
 void stat_count(char *name safe);
 
 void stat_free(void);
+
+/*
+ * Memory allocation tracking
+ */
+
+struct mempool {
+       char *name;
+       long bytes;
+       long allocations;
+       long max_bytes;
+       struct list_head linkage;
+};
+
+#define MEMPOOL(__name)                                                        \
+       struct mempool mem ## __name = {                                \
+               .name = #__name,                                        \
+               .linkage = LIST_HEAD_INIT(mem ## __name.linkage),       \
+       }
+
+void *safe __alloc(struct mempool *pool safe, int size, int zero);
+void __unalloc(struct mempool *pool safe, void *obj, int size);
+
+#define alloc(var, pool)                                               \
+       do { var = __alloc(&mem##pool, sizeof((var)[0]), 1); } while (0)
+
+#define alloc_buf(size, pool) __alloc(&mem##pool, size, 0)
+
+#define unalloc(var, pool)                                             \
+       do { __unalloc(&mem##pool, var, sizeof((var)[0])); (var)=NULL; } while (0)
+
+#define unalloc_buf(var, size, pool)                                   \
+       do { __unalloc(&mem##pool, var, size); (var) = NULL; } while(0)
+