From 6fa56c1b3831ce81b68fd866b213db1597ccdfba Mon Sep 17 00:00:00 2001 From: Yorhel <git@yorhel.nl> Date: Wed, 28 Apr 2010 15:32:47 +0200 Subject: [PATCH] Store the name of the item in the dir struct itself Rather than storing a pointer to another memory allocation in the struct. This saves some memory and improves performance by significantly decreasing the number of calls to [c|m]alloc() and free(). --- src/calc.c | 8 +++----- src/dirlist.c | 2 +- src/global.h | 14 +++++++++++--- src/util.c | 2 -- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/calc.c b/src/calc.c index 7a73878..4a0bc7d 100644 --- a/src/calc.c +++ b/src/calc.c @@ -168,13 +168,12 @@ int calc_item(struct dir *par, char *name) { return 0; /* allocate dir and fix references */ - d = calloc(sizeof(struct dir), 1); + d = calloc(SDIRSIZE+strlen(name), 1); d->parent = par; d->next = par->sub; par->sub = d; if(d->next) d->next->prev = d; - d->name = malloc(strlen(name)+1); strcpy(d->name, name); #ifdef __CYGWIN__ @@ -434,16 +433,15 @@ int calc_process() { } /* initialize parent dir */ - t = (struct dir *) calloc(1, sizeof(struct dir)); + n = orig ? strlen(orig->name) : strlen(path)+strlen(name)+1; + t = (struct dir *) calloc(1, SDIRSIZE+n); t->size = fs.st_blocks * S_BLKSIZE; t->asize = fs.st_size; t->flags |= FF_DIR; if(orig) { - t->name = malloc(strlen(orig->name)+1); strcpy(t->name, orig->name); t->parent = orig->parent; } else { - t->name = malloc(strlen(path)+strlen(name)+2); t->name[0] = 0; if(strcmp(path, "/")) strcpy(t->name, path); diff --git a/src/dirlist.c b/src/dirlist.c index 2239914..db0bd0d 100644 --- a/src/dirlist.c +++ b/src/dirlist.c @@ -197,7 +197,7 @@ void dirlist_open(struct dir *d) { dirlist_parent_alloc.flags &= ~FF_BSEL; if(head->parent->parent) { dirlist_parent = &dirlist_parent_alloc; - dirlist_parent->name = ".."; + strcpy(dirlist_parent->name, ".."); dirlist_parent->next = head; dirlist_parent->parent = head->parent; dirlist_parent->sub = head->parent; diff --git a/src/global.h b/src/global.h index e48a58b..ceb1a2b 100644 --- a/src/global.h +++ b/src/global.h @@ -53,13 +53,21 @@ * fixed-size integers instead, which are much more predictable */ struct dir { struct dir *parent, *next, *prev, *sub, *hlnk; - char *name; off_t size, asize; + ino_t ino; unsigned long items; - unsigned char flags; dev_t dev; - ino_t ino; + unsigned char flags; + char name[3]; /* must be large enough to hold ".." */ }; +/* sizeof(total dir) = SDIRSIZE + strlen(name) = sizeof(struct dir) - 3 + strlen(name) + 1 */ +#define SDIRSIZE (sizeof(struct dir)-2) + +/* Ideally, the name array should be as large as the padding added to the end of + * the struct, but I can't figure out a portable way to calculate this. We can + * be sure that it's at least 3 bytes, though, as the struct is aligned to at + * least 4 bytes and the flags field is a single byte. */ + /* program state */ extern int pstate; diff --git a/src/util.c b/src/util.c index a0dc92d..bea2483 100644 --- a/src/util.c +++ b/src/util.c @@ -211,7 +211,6 @@ void freedir_rec(struct dir *dr) { freedir_hlnk(tmp); /* remove item */ if(tmp->sub) freedir_rec(tmp->sub); - free(tmp->name); tmp2 = tmp->next; free(tmp); } @@ -245,7 +244,6 @@ void freedir(struct dir *dr) { tmp->items -= dr->items+1; } - free(dr->name); free(dr); } -- GitLab