alloc.con commit Merge branch 'ot/mru-on-list' (afc8aa3)
   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
  21union any_object {
  22        struct object object;
  23        struct blob blob;
  24        struct tree tree;
  25        struct commit commit;
  26        struct tag tag;
  27};
  28
  29struct 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
  35static 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
  51static struct alloc_state blob_state;
  52void *alloc_blob_node(void)
  53{
  54        struct blob *b = alloc_node(&blob_state, sizeof(struct blob));
  55        b->object.type = OBJ_BLOB;
  56        return b;
  57}
  58
  59static struct alloc_state tree_state;
  60void *alloc_tree_node(void)
  61{
  62        struct tree *t = alloc_node(&tree_state, sizeof(struct tree));
  63        t->object.type = OBJ_TREE;
  64        return t;
  65}
  66
  67static struct alloc_state tag_state;
  68void *alloc_tag_node(void)
  69{
  70        struct tag *t = alloc_node(&tag_state, sizeof(struct tag));
  71        t->object.type = OBJ_TAG;
  72        return t;
  73}
  74
  75static struct alloc_state object_state;
  76void *alloc_object_node(void)
  77{
  78        struct object *obj = alloc_node(&object_state, sizeof(union any_object));
  79        obj->type = OBJ_NONE;
  80        return obj;
  81}
  82
  83static struct alloc_state commit_state;
  84
  85unsigned int alloc_commit_index(void)
  86{
  87        static unsigned int count;
  88        return count++;
  89}
  90
  91void *alloc_commit_node(void)
  92{
  93        struct commit *c = alloc_node(&commit_state, sizeof(struct commit));
  94        c->object.type = OBJ_COMMIT;
  95        c->index = alloc_commit_index();
  96        return c;
  97}
  98
  99static void report(const char *name, unsigned int count, size_t size)
 100{
 101        fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n",
 102                        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
 108void alloc_report(void)
 109{
 110        REPORT(blob, struct blob);
 111        REPORT(tree, struct tree);
 112        REPORT(commit, struct commit);
 113        REPORT(tag, struct tag);
 114        REPORT(object, union any_object);
 115}