Linus Torvalds | 855419f | 2006-06-19 10:44:15 -0700 | [diff] [blame] | 1 | /* |
| 2 | * alloc.c - specialized allocator for internal objects |
| 3 | * |
| 4 | * Copyright (C) 2006 Linus Torvalds |
| 5 | * |
| 6 | * The standard malloc/free wastes too much space for objects, partly because |
| 7 | * it maintains all the allocation infrastructure (which isn't needed, since |
| 8 | * we never free an object descriptor anyway), but even more because it ends |
| 9 | * up with maximal alignment because it doesn't know what the object alignment |
| 10 | * for the new allocation is. |
| 11 | */ |
| 12 | #include "cache.h" |
| 13 | #include "object.h" |
| 14 | #include "blob.h" |
| 15 | #include "tree.h" |
| 16 | #include "commit.h" |
| 17 | #include "tag.h" |
| 18 | |
| 19 | #define BLOCKING 1024 |
| 20 | |
Linus Torvalds | 2c1cbec | 2007-04-16 22:10:19 -0700 | [diff] [blame] | 21 | union any_object { |
| 22 | struct object object; |
| 23 | struct blob blob; |
| 24 | struct tree tree; |
| 25 | struct commit commit; |
| 26 | struct tag tag; |
| 27 | }; |
| 28 | |
Ramsay Jones | 225ea22 | 2014-07-13 02:41:41 -0400 | [diff] [blame] | 29 | struct alloc_state { |
| 30 | int count; /* total number of nodes allocated */ |
| 31 | int nr; /* number of nodes left in current allocation */ |
| 32 | void *p; /* first free node in current allocation */ |
| 33 | }; |
| 34 | |
| 35 | static inline void *alloc_node(struct alloc_state *s, size_t node_size) |
| 36 | { |
| 37 | void *ret; |
| 38 | |
| 39 | if (!s->nr) { |
| 40 | s->nr = BLOCKING; |
| 41 | s->p = xmalloc(BLOCKING * node_size); |
| 42 | } |
| 43 | s->nr--; |
| 44 | s->count++; |
| 45 | ret = s->p; |
| 46 | s->p = (char *)s->p + node_size; |
| 47 | memset(ret, 0, node_size); |
| 48 | return ret; |
| 49 | } |
| 50 | |
Jeff King | 600e2a6 | 2014-07-13 02:41:51 -0400 | [diff] [blame] | 51 | static struct alloc_state blob_state; |
| 52 | void *alloc_blob_node(void) |
| 53 | { |
| 54 | struct blob *b = alloc_node(&blob_state, sizeof(struct blob)); |
Jeff King | d36f51c | 2014-07-13 02:41:55 -0400 | [diff] [blame] | 55 | b->object.type = OBJ_BLOB; |
Jeff King | 600e2a6 | 2014-07-13 02:41:51 -0400 | [diff] [blame] | 56 | return b; |
| 57 | } |
| 58 | |
| 59 | static struct alloc_state tree_state; |
| 60 | void *alloc_tree_node(void) |
| 61 | { |
| 62 | struct tree *t = alloc_node(&tree_state, sizeof(struct tree)); |
Jeff King | d36f51c | 2014-07-13 02:41:55 -0400 | [diff] [blame] | 63 | t->object.type = OBJ_TREE; |
Jeff King | 600e2a6 | 2014-07-13 02:41:51 -0400 | [diff] [blame] | 64 | return t; |
| 65 | } |
| 66 | |
| 67 | static struct alloc_state tag_state; |
| 68 | void *alloc_tag_node(void) |
| 69 | { |
| 70 | struct tag *t = alloc_node(&tag_state, sizeof(struct tag)); |
Jeff King | d36f51c | 2014-07-13 02:41:55 -0400 | [diff] [blame] | 71 | t->object.type = OBJ_TAG; |
Jeff King | 600e2a6 | 2014-07-13 02:41:51 -0400 | [diff] [blame] | 72 | return t; |
| 73 | } |
| 74 | |
| 75 | static struct alloc_state object_state; |
| 76 | void *alloc_object_node(void) |
| 77 | { |
| 78 | struct object *obj = alloc_node(&object_state, sizeof(union any_object)); |
Jeff King | d36f51c | 2014-07-13 02:41:55 -0400 | [diff] [blame] | 79 | obj->type = OBJ_NONE; |
Jeff King | 600e2a6 | 2014-07-13 02:41:51 -0400 | [diff] [blame] | 80 | return obj; |
| 81 | } |
Linus Torvalds | 855419f | 2006-06-19 10:44:15 -0700 | [diff] [blame] | 82 | |
Ramsay Jones | 225ea22 | 2014-07-13 02:41:41 -0400 | [diff] [blame] | 83 | static struct alloc_state commit_state; |
| 84 | |
Jeff King | 94d5a22 | 2014-07-13 02:42:08 -0400 | [diff] [blame] | 85 | unsigned int alloc_commit_index(void) |
| 86 | { |
| 87 | static unsigned int count; |
| 88 | return count++; |
| 89 | } |
| 90 | |
Jeff King | 969eba6 | 2014-06-10 17:39:04 -0400 | [diff] [blame] | 91 | void *alloc_commit_node(void) |
| 92 | { |
Ramsay Jones | 225ea22 | 2014-07-13 02:41:41 -0400 | [diff] [blame] | 93 | struct commit *c = alloc_node(&commit_state, sizeof(struct commit)); |
Jeff King | d36f51c | 2014-07-13 02:41:55 -0400 | [diff] [blame] | 94 | c->object.type = OBJ_COMMIT; |
Jeff King | 94d5a22 | 2014-07-13 02:42:08 -0400 | [diff] [blame] | 95 | c->index = alloc_commit_index(); |
Jeff King | 969eba6 | 2014-06-10 17:39:04 -0400 | [diff] [blame] | 96 | return c; |
| 97 | } |
| 98 | |
Felipe Contreras | 4b25d09 | 2009-05-01 12:06:36 +0300 | [diff] [blame] | 99 | static void report(const char *name, unsigned int count, size_t size) |
Ramsay Allan Jones | 579d1fb | 2006-07-30 16:38:28 +0100 | [diff] [blame] | 100 | { |
Jonathan Nieder | 28bd70d | 2011-03-16 00:15:31 -0500 | [diff] [blame] | 101 | fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n", |
| 102 | name, count, (uintmax_t) size); |
Ramsay Allan Jones | 579d1fb | 2006-07-30 16:38:28 +0100 | [diff] [blame] | 103 | } |
| 104 | |
Jeff King | c335d74 | 2014-06-10 17:38:47 -0400 | [diff] [blame] | 105 | #define REPORT(name, type) \ |
Ramsay Jones | 225ea22 | 2014-07-13 02:41:41 -0400 | [diff] [blame] | 106 | report(#name, name##_state.count, name##_state.count * sizeof(type) >> 10) |
Linus Torvalds | 855419f | 2006-06-19 10:44:15 -0700 | [diff] [blame] | 107 | |
| 108 | void alloc_report(void) |
| 109 | { |
Jeff King | c335d74 | 2014-06-10 17:38:47 -0400 | [diff] [blame] | 110 | REPORT(blob, struct blob); |
| 111 | REPORT(tree, struct tree); |
Ramsay Jones | 225ea22 | 2014-07-13 02:41:41 -0400 | [diff] [blame] | 112 | REPORT(commit, struct commit); |
Jeff King | c335d74 | 2014-06-10 17:38:47 -0400 | [diff] [blame] | 113 | REPORT(tag, struct tag); |
| 114 | REPORT(object, union any_object); |
Linus Torvalds | 855419f | 2006-06-19 10:44:15 -0700 | [diff] [blame] | 115 | } |