alloc.c 2.57 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * alloc.c  - specialized allocator for internal objects
 *
 * Copyright (C) 2006 Linus Torvalds
 *
 * The standard malloc/free wastes too much space for objects, partly because
 * it maintains all the allocation infrastructure (which isn't needed, since
 * we never free an object descriptor anyway), but even more because it ends
 * up with maximal alignment because it doesn't know what the object alignment
 * for the new allocation is.
 */
#include "cache.h"
#include "object.h"
#include "blob.h"
#include "tree.h"
#include "commit.h"
#include "tag.h"

#define BLOCKING 1024

21 22 23 24 25 26 27 28
union any_object {
	struct object object;
	struct blob blob;
	struct tree tree;
	struct commit commit;
	struct tag tag;
};

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
struct alloc_state {
	int count; /* total number of nodes allocated */
	int nr;    /* number of nodes left in current allocation */
	void *p;   /* first free node in current allocation */
};

static inline void *alloc_node(struct alloc_state *s, size_t node_size)
{
	void *ret;

	if (!s->nr) {
		s->nr = BLOCKING;
		s->p = xmalloc(BLOCKING * node_size);
	}
	s->nr--;
	s->count++;
	ret = s->p;
	s->p = (char *)s->p + node_size;
	memset(ret, 0, node_size);
	return ret;
}

51 52 53 54
static struct alloc_state blob_state;
void *alloc_blob_node(void)
{
	struct blob *b = alloc_node(&blob_state, sizeof(struct blob));
55
	b->object.type = OBJ_BLOB;
56 57 58 59 60 61 62
	return b;
}

static struct alloc_state tree_state;
void *alloc_tree_node(void)
{
	struct tree *t = alloc_node(&tree_state, sizeof(struct tree));
63
	t->object.type = OBJ_TREE;
64 65 66 67 68 69 70
	return t;
}

static struct alloc_state tag_state;
void *alloc_tag_node(void)
{
	struct tag *t = alloc_node(&tag_state, sizeof(struct tag));
71
	t->object.type = OBJ_TAG;
72 73 74 75 76 77 78
	return t;
}

static struct alloc_state object_state;
void *alloc_object_node(void)
{
	struct object *obj = alloc_node(&object_state, sizeof(union any_object));
79
	obj->type = OBJ_NONE;
80 81
	return obj;
}
82

83 84
static struct alloc_state commit_state;

85 86 87 88 89 90
unsigned int alloc_commit_index(void)
{
	static unsigned int count;
	return count++;
}

91 92
void *alloc_commit_node(void)
{
93
	struct commit *c = alloc_node(&commit_state, sizeof(struct commit));
94
	c->object.type = OBJ_COMMIT;
95
	c->index = alloc_commit_index();
96 97 98
	return c;
}

99
static void report(const char *name, unsigned int count, size_t size)
100
{
101 102
	fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n",
			name, count, (uintmax_t) size);
103 104
}

105
#define REPORT(name, type)	\
106
    report(#name, name##_state.count, name##_state.count * sizeof(type) >> 10)
107 108 109

void alloc_report(void)
{
110 111
	REPORT(blob, struct blob);
	REPORT(tree, struct tree);
112
	REPORT(commit, struct commit);
113 114
	REPORT(tag, struct tag);
	REPORT(object, union any_object);
115
}