This commit was manufactured by cvs2svn to create branch 'gomp-branch'.
[official-gcc.git] / libstdc++-v3 / docs / html / ext / ballocator_doc.txt
blob2173b618f4f8836f35ed833c308a8b0a95a89879
1                         BITMAPPED ALLOCATOR
2                         ===================
4 2004-03-11  Dhruv Matani  <dhruvbird@HotPOP.com>
6 ---------------------------------------------------------------------
8 As this name suggests, this allocator uses a bit-map to keep track of
9 the used and unused memory locations for it's book-keeping purposes.
11 This allocator will make use of 1 single bit to keep track of whether
12 it has been allocated or not. A bit 1 indicates free, while 0
13 indicates allocated. This has been done so that you can easily check a
14 collection of bits for a free block. This kind of Bitmapped strategy
15 works best for single object allocations, and with the STL type
16 parameterized allocators, we do not need to choose any size for the
17 block which will be represented by a single bit. This will be the size
18 of the parameter around which the allocator has been
19 parameterized. Thus, close to optimal performance will result. Hence,
20 this should be used for node based containers which call the allocate
21 function with an argument of 1.
23 The bitmapped allocator's internal pool is exponentially
24 growing. Meaning that internally, the blocks acquired from the Free
25 List Store will double every time the bitmapped allocator runs out of
26 memory.
28 --------------------------------------------------------------------
30 The macro __GTHREADS decides whether to use Mutex Protection around
31 every allocation/deallocation.  The state of the macro is picked up
32 automatically from the gthr abstration layer.
34 ----------------------------------------------------------------------
36 What is the Free List Store?
37 ----------------------------
39 The Free List Store (referred to as FLS for the remaining part of this
40 document) is the Global memory pool that is shared by all instances of
41 the bitmapped allocator instantiated for any type. This maintains a
42 sorted order of all free memory blocks given back to it by the
43 bitmapped allocator, and is also responsible for giving memory to the
44 bitmapped allocator when it asks for more.
46 Internally, there is a Free List threshold which indicates the Maximum
47 number of free lists that the FLS can hold internally
48 (cache). Currently, this value is set at 64. So, if there are more
49 than 64 free lists coming in, then some of them will be given back to
50 the OS using operator delete so that at any given time the Free List's
51 size does not exceed 64 entries. This is done because a Binary Search
52 is used to locate an entry in a free list when a request for memory
53 comes along. Thus, the run-time complexity of the search would go up
54 given an increasing size, for 64 entries however, lg(64) == 6
55 comparisons are enough to locate the correct free list if it exists.
57 Suppose the free list size has reached it's threshold, then the
58 largest block from among those in the list and the new block will be
59 selected and given back to the OS. This is done because it reduces
60 external fragmentation, and allows the OS to use the larger blocks
61 later in an orderly fashion, possibly merging them later. Also, on
62 some systems, large blocks are obtained via calls to mmap, so giving
63 them back to free system resources becomes most important.
65 The function _S_should_i_give decides the policy that determines
66 whether the current block of memory should be given to the allocator
67 for the request that it has made. That's because we may not always
68 have exact fits for the memory size that the allocator requests. We do
69 this mainly to prevent external fragmentation at the cost of a little
70 internal fragmentation. Now, the value of this internal fragmentation
71 has to be decided by this function. I can see 3 possibilities right
72 now. Please add more as and when you find better strategies.
74 1. Equal size check. Return true only when the 2 blocks are of equal
75    size.
77 2. Difference Threshold: Return true only when the _block_size is
78    greater than or equal to the _required_size, and if the _BS is >
79    _RS by a difference of less than some THRESHOLD value, then return
80    true, else return false.  
82 3. Percentage Threshold. Return true only when the _block_size is
83    greater than or equal to the _required_size, and if the _BS is >
84    _RS by a percentage of less than some THRESHOLD value, then return
85    true, else return false.
87 Currently, (3) is being used with a value of 36% Maximum wastage per
88 Super Block.
90 --------------------------------------------------------------------
92 1) What is a super block? Why is it needed?
94    A super block is the block of memory acquired from the FLS from
95    which the bitmap allocator carves out memory for single objects and
96    satisfies the user's requests. These super blocks come in sizes that
97    are powers of 2 and multiples of 32 (_Bits_Per_Block). Yes both at
98    the same time! That's because the next super block acquired will be
99    2 times the previous one, and also all super blocks have to be
100    multiples of the _Bits_Per_Block value.
102 2) How does it interact with the free list store?
104    The super block is contained in the FLS, and the FLS is responsible
105    for getting / returning Super Bocks to and from the OS using
106    operator new as defined by the C++ standard.
108 ---------------------------------------------------------------------
110 How does the allocate function Work?
111 ------------------------------------
113 The allocate function is specialized for single object allocation
114 ONLY. Thus, ONLY if n == 1, will the bitmap_allocator's specialized
115 algorithm be used. Otherwise, the request is satisfied directly by
116 calling operator new.
118 Suppose n == 1, then the allocator does the following:
120 1. Checks to see whether the a free block exists somewhere in a region
121    of memory close to the last satisfied request. If so, then that
122    block is marked as allocated in the bit map and given to the
123    user. If not, then (2) is executed.
125 2. Is there a free block anywhere after the current block right upto
126    the end of the memory that we have? If so, that block is found, and
127    the same procedure is applied as above, and returned to the
128    user. If not, then (3) is executed.
130 3. Is there any block in whatever region of memory that we own free?
131    This is done by checking (a) The use count for each super block,
132    and if that fails then (b) The individual bit-maps for each super
133    block. Note: Here we are never touching any of the memory that the
134    user will be given, and we are confining all memory accesses to a
135    small region of memory! This helps reduce cache misses. If this
136    succeeds then we apply the same procedure on that bit-map as (1),
137    and return that block of memory to the user. However, if this
138    process fails, then we resort to (4).
140 4. This process involves Refilling the internal exponentially growing
141    memory pool. The said effect is achieved by calling _S_refill_pool
142    which does the following:
143          (a). Gets more memory from the Global Free List of the
144               Required size.
145          (b). Adjusts the size for the next call to itself.
146          (c). Writes the appropriate headers in the bit-maps.
147          (d). Sets the use count for that super-block just allocated
148               to 0 (zero).
149          (e). All of the above accounts to maintaining the basic
150               invariant for the allocator. If the invariant is
151               maintained, we are sure that all is well.
152    Now, the same process is applied on the newly acquired free blocks,
153    which are dispatched accordingly.
155 Thus, you can clearly see that the allocate function is nothing but a
156 combination of the next-fit and first-fit algorithm optimized ONLY for
157 single object allocations.
160 -------------------------------------------------------------------------
162 How does the deallocate function work?
163 --------------------------------------
165 The deallocate function again is specialized for single objects ONLY.
166 For all n belonging to > 1, the operator delete is called without
167 further ado, and the deallocate function returns.
169 However for n == 1, a series of steps are performed:
171 1. We first need to locate that super-block which holds the memory
172    location given to us by the user. For that purpose, we maintain a
173    static variable _S_last_dealloc_index, which holds the index into
174    the vector of block pairs which indicates the index of the last
175    super-block from which memory was freed. We use this strategy in
176    the hope that the user will deallocate memory in a region close to
177    what he/she deallocated the last time around. If the check for
178    belongs_to succeeds, then we determine the bit-map for the given
179    pointer, and locate the index into that bit-map, and mark that bit
180    as free by setting it.
182 2. If the _S_last_dealloc_index does not point to the memory block
183    that we're looking for, then we do a linear search on the block
184    stored in the vector of Block Pairs. This vector in code is called
185    _S_mem_blocks. When the corresponding super-block is found, we
186    apply the same procedure as we did for (1) to mark the block as
187    free in the bit-map.
189 Now, whenever a block is freed, the use count of that particular super
190 block goes down by 1. When this use count hits 0, we remove that super
191 block from the list of all valid super blocks stored in the
192 vector. While doing this, we also make sure that the basic invariant
193 is maintained by making sure that _S_last_request and
194 _S_last_dealloc_index point to valid locations within the vector.
196 --------------------------------------------------------------------
199 Data Layout for a Super Block:
200 ==============================
202 Each Super Block will be of some size that is a multiple of the number
203 of Bits Per Block. Typically, this value is chosen as Bits_Per_Byte X
204 sizeof(unsigned int). On an X86 system, this gives the figure 
205 8 X 4 = 32. Thus, each Super Block will be of size 32 X Some_Value.
206 This Some_Value is sizeof(value_type). For now, let it be called 'K'.
207 Thus, finally, Super Block size is 32 X K bytes.
209 This value of 32 has been chosen because each unsigned int has 32-bits
210 and Maximum use of these can be made with such a figure.
212 Consider a block of size 32 ints.
213 In memory, it would look like this:
215 ---------------------------------------------------------------------
216 |   136   |    0    | 4294967295 |      Data-> Space for 32-ints    |
217 ---------------------------------------------------------------------
219 The first Columns represents the size of the Block in bytes as seen by
220 the Bitmap Allocator. Internally, a global free list is used to keep
221 track of the free blocks used and given back by the bitmap
222 allocator. It is this Free List Store that is responsible for writing
223 and managing this information. Actually the number of bytes allocated
224 in this case would be: 4 + 4 + 4 + 32*4 = 140 bytes, but the first 4
225 bytes are an addition by the Free List Store, so the Bitmap Allocator
226 sees only 136 bytes. These first 4 bytes about which the bitmapped
227 allocator is not aware hold the value 136.
229 What do the remaining values represent?
230 ---------------------------------------
232 The 2nd 4 in the expression is the sizeof(unsigned int) because the
233 Bitmapped Allocator maintains a used count for each Super Block, which
234 is initially set to 0 (as indicated in the diagram). This is
235 incremented every time a block is removed from this super block
236 (allocated), and decremented whenever it is given back. So, when the
237 used count falls to 0, the whole super block will be given back to the
238 Free List Store.
240 The value 4294967295 represents the integer corresponding to the
241 bit representation of all bits set: 11111111111111111111111111111111.
243 The 3rd 4 is size of the bitmap itself, which is the size of 32-bits,
244 which is 4-bytes, or 1 X sizeof(unsigned int).
247 --------------------------------------------------------------------
249 Another issue would be whether to keep the all bitmaps in a separate
250 area in memory, or to keep them near the actual blocks that will be
251 given out or allocated for the client. After some testing, I've
252 decided to keep these bitmaps close to the actual blocks. this will
253 help in 2 ways. 
255 1. Constant time access for the bitmap themselves, since no kind of
256    look up will be needed to find the correct bitmap list or it's
257    equivalent.
259 2. And also this would preserve the cache as far as possible.
261 So in effect, this kind of an allocator might prove beneficial from a
262 purely cache point of view. But this allocator has been made to try
263 and roll out the defects of the node_allocator, wherein the nodes get
264 skewed about in memory, if they are not returned in the exact reverse
265 order or in the same order in which they were allocated. Also, the
266 new_allocator's book keeping overhead is too much for small objects
267 and single object allocations, though it preserves the locality of
268 blocks very well when they are returned back to the allocator.
270 -------------------------------------------------------------------
272 Expected overhead per block would be 1 bit in memory. Also, once
273 the address of the free list has been found, the cost for
274 allocation/deallocation would be negligible, and is supposed to be
275 constant time. For these very reasons, it is very important to
276 minimize the linear time costs, which include finding a free list
277 with a free block while allocating, and finding the corresponding
278 free list for a block while deallocating. Therefore, I have decided
279 that the growth of the internal pool for this allocator will be
280 exponential as compared to linear for node_allocator. There, linear
281 time works well, because we are mainly concerned with speed of
282 allocation/deallocation and memory consumption, whereas here, the
283 allocation/deallocation part does have some linear/logarithmic
284 complexity components in it. Thus, to try and minimize them would
285 be a good thing to do at the cost of a little bit of memory.
287 Another thing to be noted is the the pool size will double every time
288 the internal pool gets exhausted, and all the free blocks have been
289 given away. The initial size of the pool would be sizeof(unsigned
290 int)*8 which is the number of bits in an integer, which can fit
291 exactly in a CPU register. Hence, the term given is exponential growth
292 of the internal pool.
294 ---------------------------------------------------------------------
296 After reading all this, you may still have a few questions about the
297 internal working of this allocator, like my friend had!
299 Well here are the exact questions that he posed:
301 1) The "Data Layout" section is cryptic. I have no idea of what you
302    are trying to say. Layout of what? The free-list? Each bitmap? The
303    Super Block?
305    The layout of a Super Block of a given size. In the example, a super
306    block of size 32 X 1 is taken. The general formula for calculating
307    the size of a super block is 32*sizeof(value_type)*2^n, where n
308    ranges from 0 to 32 for 32-bit systems.
310 2) And since I just mentioned the term `each bitmap', what in the
311    world is meant by it? What does each bitmap manage? How does it
312    relate to the super block? Is the Super Block a bitmap as well?
314    Good question! Each bitmap is part of a Super Block which is made up
315    of 3 parts as I have mentioned earlier. Re-iterating, 1. The use
316    count, 2. The bit-map for that Super Block. 3. The actual memory
317    that will be eventually given to the user. Each bitmap is a multiple
318    of 32 in size. If there are 32*(2^3) blocks of single objects to be
319    given, there will be '32*(2^3)' bits present. Each 32 bits managing
320    the allocated / free status for 32 blocks. Since each unsigned int
321    contains 32-bits, one unsigned int can manage upto 32 blocks'
322    status. Each bit-map is made up of a number of unsigned ints, whose
323    exact number for a super-block of a given size I have just
324    mentioned.
326 3) How do the allocate and deallocate functions work in regard to
327    bitmaps?
329    The allocate and deallocate functions manipulate the bitmaps and have
330    nothing to do with the memory that is given to the user. As I have
331    earlier mentioned, a 1 in the bitmap's bit field indicates free,
332    while a 0 indicates allocated. This lets us check 32 bits at a time
333    to check whether there is at lease one free block in those 32 blocks
334    by testing for equality with (0). Now, the allocate function will
335    given a memory block find the corresponding bit in the bitmap, and
336    will reset it (ie. make it re-set (0)). And when the deallocate
337    function is called, it will again set that bit after locating it to
338    indicate that that particular block corresponding to this bit in the
339    bit-map is not being used by anyone, and may be used to satisfy
340    future requests.
342 ----------------------------------------------------------------------
344 (Tech-Stuff, Please stay out if you are not interested in the
345 selection of certain constants. This has nothing to do with the
346 algorithm per-se, only with some vales that must be chosen correctly
347 to ensure that the allocator performs well in a real word scenario,
348 and maintains a good balance between the memory consumption and the
349 allocation/deallocation speed).
351 The formula for calculating the maximum wastage as a percentage:
353 (32 X k + 1) / (2 X (32 X k + 1 + 32 X c)) X 100.
355 Where,
356         k => The constant overhead per node. eg. for list, it is 8
357         bytes, and for map it is 12 bytes.
358         c => The size of the base type on which the map/list is
359         instantiated. Thus, suppose the the type1 is int and type2 is
360         double, they are related by the relation sizeof(double) ==
361         2*sizeof(int). Thus, all types must have this double size
362         relation for this formula to work properly.
364 Plugging-in: For List: k = 8 and c = 4 (int and double), we get:
365 33.376%
367 For map/multimap: k = 12, and c = 4 (int and double), we get:
368 37.524%
370 Thus, knowing these values, and based on the sizeof(value_type), we
371 may create a function that returns the Max_Wastage_Percentage for us
372 to use.