Hash :
08b318c0
Author :
Date :
2018-03-14T10:43:00
stdalloc: extend allocators by file and line
Our desired architecture would make allocators completely pluggable,
such that users of libgit2 can swap out memory allocators at runtime.
While making e.g. debugging easier by not having to do a separate build,
this feature can also help maintainers of bindings for libgit2 by tying
the memory allocations into the other language's memory system.
In order to do so, though, we first need to make our two different
pre-existing allocators "stdalloc" and "crtdbg" have the same function
signatures, as the "crtdbg" allocators all have an additional file and
line argument. This is required to build correct stack traces for
debugging memory allocations. As that feature may also be interesting to
authors of other applications for debugging libgit2, we now simply add
these arguments to our standard allocators.
Obviously, this may come with a performance penalty. During some simple
benchmarks no real impact could be measured though in contrast to a
simple pluggable allocator. The following table summarizes the
benchmarks. There were three different builds with our current standard
allocator ("standard"), with pluggable authenticators accessed via
function pointers ("pluggable") and for pluggable authenticators with
file and line being added ("fileline"). Furthermore, there were three
scenarios for 100.000.000 allocations of 100B ("small alloc"),
100.000.000 allocations of 100KB ("medium alloc"), and 1.000.000
allocations of 100MB. All results are best of 10 runs.
|------------|-------------------|-------------------|-------------------|
| build/test | small alloc | medium alloc | big alloc |
|------------|-------------------|-------------------|-------------------|
| standard | 4539779566, +0.0% | 5912927186, +0.0% | 5166935308, +0.0% |
|------------|-------------------|-------------------|-------------------|
| pluggable | 4611074505, +1.5% | 5979185308, +1.1% | 5388776352, +4.2% |
|------------|-------------------|-------------------|-------------------|
| fileline | 4588338192, +1.1% | 6004951910, +1.5% | 4942528135, -4.4% |
|------------|-------------------|-------------------|-------------------|
As can be seen, there is a performance overhead for pluggable
allocators. Furthermore, it can also be seen that there is some big
variance between runs, especially in the "big alloc" scenario. This is
probably being caused by nondeterministic behaviour in the kernel for
dynamic allocations. Still, it can be observed that there should be no
real difference between the "pluggable" and "fileline" allocators.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_alloc_h__
#define INCLUDE_alloc_h__
#include "git2/sys/alloc.h"
extern git_allocator git__allocator;
#define git__malloc(len) git__allocator.gmalloc(len, __FILE__, __LINE__)
#define git__calloc(nelem, elsize) git__allocator.gcalloc(nelem, elsize, __FILE__, __LINE__)
#define git__strdup(str) git__allocator.gstrdup(str, __FILE__, __LINE__)
#define git__strndup(str, n) git__allocator.gstrndup(str, n, __FILE__, __LINE__)
#define git__substrdup(str, n) git__allocator.gsubstrdup(str, n, __FILE__, __LINE__)
#define git__realloc(ptr, size) git__allocator.grealloc(ptr, size, __FILE__, __LINE__)
#define git__reallocarray(ptr, nelem, elsize) git__allocator.greallocarray(ptr, nelem, elsize, __FILE__, __LINE__)
#define git__mallocarray(nelem, elsize) git__allocator.gmallocarray(nelem, elsize, __FILE__, __LINE__)
#define git__free git__allocator.gfree
/**
* This function is being called by our global setup routines to
* initialize the standard allocator.
*/
int git_allocator_global_init(void);
/**
* Switch out libgit2's global memory allocator
*
* @param allocator The new allocator that should be used. All function pointers
* of it need to be set correctly.
* @return An error code or 0.
*/
int git_allocator_setup(git_allocator *allocator);
#endif