summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2010-04-28 15:32:47 +0200
committerYorhel <git@yorhel.nl>2010-04-28 15:32:47 +0200
commit6fa56c1b3831ce81b68fd866b213db1597ccdfba (patch)
treec7516e1246198db8b2e67775c456f2eb877fa722
parentb7ccf78b90f7fded5f6627babcd7b0e92ac807fd (diff)
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().
-rw-r--r--src/calc.c8
-rw-r--r--src/dirlist.c2
-rw-r--r--src/global.h14
-rw-r--r--src/util.c2
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);
}