1/**
2@page libtalloc_pools Chapter 5: Memory pools
3
4@section pools Memory pools
5
6Allocation of a new memory is an expensive operation and large programs can
7contain thousands of calls of malloc() for a single computation, where every
8call allocates only a very small amount of the memory. This can result in an
9undesirable slowdown of the application. We can avoid this slowdown by
10decreasing the number of malloc() calls by using a memory pool.
11
12A memory pool is a preallocated memory space with a fixed size. If we need to
13allocate new data we will take the desired amount of the memory from the pool
14instead of requesting a new memory from the system. This is done by creating a
15pointer that points inside the preallocated memory. Such a pool must not be
16reallocated as it would change its location - pointers that were pointing
17inside the pool would become invalid. Therefore, a memory pool requires a very
18good estimate of the required memory space.
19
20The talloc library contains its own implementation of a memory pool. It is
21highly transparent for the programmer. The only thing that needs to be done is
22an initialization of a new pool context using talloc_pool() -
23which can be used in the same way as any other context.
24
25Refactoring of existing code (that uses talloc) to take the advantage of a
26memory pool is quite simple due to the following properties of the pool context:
27
28- if we are allocating data on a pool context, it takes the desired
29  amount of memory from the pool,
30- if the context is a descendant of the pool context, it takes the space
31  from the pool as well,
32- if the pool does not have sufficient portion of memory left, it will
33  create a new non-pool context, leaving the pool intact
34
35@code
36/* allocate 1KiB in a pool */
37TALLOC_CTX *pool_ctx = talloc_pool(NULL, 1024);
38
39/* Take 512B from the pool, 512B is left there */
40void *ptr = talloc_size(pool_ctx, 512);
41
42/* 1024B > 512B, this will create new talloc chunk outside
43   the pool */
44void *ptr2 = talloc_size(ptr, 1024);
45
46/* The pool still contains 512 free bytes
47 * this will take 200B from them. */
48void *ptr3 = talloc_size(ptr, 200);
49
50/* This will destroy context 'ptr3' but the memory
51 * is not freed, the available space in the pool
52 * will increase to 512B. */
53talloc_free(ptr3);
54
55/* This will free memory taken by 'pool_ctx'
56 * and 'ptr2' as well. */
57talloc_free(pool_ctx);
58@endcode
59
60The above given is very convenient, but there is one big issue to be kept in
61mind. If the parent of a talloc pool child is changed to a parent that is
62outside of this pool, the whole pool memory will not be freed until the child is
63freed. For this reason we must be very careful when stealing a descendant of a
64pool context.
65
66@code
67TALLOC_CTX *mem_ctx = talloc_new(NULL);
68TALLOC_CTX *pool_ctx = talloc_pool(NULL, 1024);
69struct foo *foo = talloc(pool_ctx, struct foo);
70
71/* mem_ctx is not in the pool */
72talloc_steal(mem_ctx, foo);
73
74/* pool_ctx is marked as freed but the memory is not
75   deallocated, accessing the pool_ctx again will cause
76   an error */
77talloc_free(pool_ctx);
78
79/* This deallocates the pool_ctx. */
80talloc_free(mem_ctx);
81@endcode
82
83It may often be better to copy the memory we want instead of stealing it to
84avoid this problem. If we do not need to retain the context name (to keep the
85type information), we can use talloc_memdup() to do this.
86
87Copying the memory out of the pool may, however, discard all the performance
88boost given by the pool, depending on the size of the copied memory. Therefore,
89the code should be well profiled before taking this path. In general, the
90golden rule is: if we need to steal from the pool context, we should not
91use a pool context.
92
93*/
94