OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libstdc++-v3/] [docs/] [html/] [ext/] [ballocator_doc.html] - Blame information for rev 20

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 20 jlechner
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
2
<html>
3
<head>
4
  <meta content="text/html; charset=ISO-8859-1"
5
 http-equiv="content-type">
6
  <title>Bitmap Allocator</title>
7
  <meta content="Dhruv Matani" name="author">
8
  <meta content="Bitmap Allocator" name="description">
9
</head>
10
<body>
11
<h1 style="text-align: center;">Bitmap Allocator</h1>
12
<em><br>
13
<small><small>The latest version of this document is always available
14
at <a
15
 href="http://gcc.gnu.org/onlinedocs/libstdc++/ext/ballocator_doc.html">
16
http://gcc.gnu.org/onlinedocs/libstdc++/ext/ballocator_doc.html</a>.</small></small></em><br>
17
<br>
18
<em> To the <a href="http://gcc.gnu.org/libstdc++/">libstdc++-v3
19
homepage</a>.</em><br>
20
<br>
21
<hr style="width: 100%; height: 2px;"><br>
22
As this name suggests, this allocator uses a bit-map to keep track of
23
the used and unused memory locations for it's book-keeping purposes.<br>
24
<br>
25
This allocator will make use of 1 single bit to keep track of whether
26
it has been allocated or not. A bit 1 indicates free, while 0 indicates
27
allocated. This has been done so that you can easily check a collection
28
of bits for a free block. This kind of Bitmapped strategy works best
29
for single object allocations, and with the STL type parameterized
30
allocators, we do not need to choose any size for the block which will
31
be represented by a single bit. This will be the size of the parameter
32
around which the allocator has been parameterized. Thus, close to
33
optimal performance will result. Hence, this should be used for node
34
based containers which call the allocate function with an argument of 1.<br>
35
<br>
36
The bitmapped allocator's internal pool is exponentially growing.
37
Meaning that internally, the blocks acquired from the Free List Store
38
will double every time the bitmapped allocator runs out of memory.<br>
39
<br>
40
<hr style="width: 100%; height: 2px;"><br>
41
The macro __GTHREADS decides whether to use Mutex Protection around
42
every allocation/deallocation. The state of the macro is picked up
43
automatically from the gthr abstration layer.<br>
44
<br>
45
<hr style="width: 100%; height: 2px;">
46
<h3 style="text-align: center;">What is the Free List Store?</h3>
47
<br>
48
The Free List Store (referred to as FLS for the remaining part of this
49
document) is the Global memory pool that is shared by all instances of
50
the bitmapped allocator instantiated for any type. This maintains a
51
sorted order of all free memory blocks given back to it by the
52
bitmapped allocator, and is also responsible for giving memory to the
53
bitmapped allocator when it asks for more.<br>
54
<br>
55
Internally, there is a Free List threshold which indicates the Maximum
56
number of free lists that the FLS can hold internally (cache).
57
Currently, this value is set at 64. So, if there are more than 64 free
58
lists coming in, then some of them will be given back to the OS using
59
operator delete so that at any given time the Free List's size does not
60
exceed 64 entries. This is done because a Binary Search is used to
61
locate an entry in a free list when a request for memory comes along.
62
Thus, the run-time complexity of the search would go up given an
63
increasing size, for 64 entries however, lg(64) == 6 comparisons are
64
enough to locate the correct free list if it exists.<br>
65
<br>
66
Suppose the free list size has reached it's threshold, then the largest
67
block from among those in the list and the new block will be selected
68
and given back to the OS. This is done because it reduces external
69
fragmentation, and allows the OS to use the larger blocks later in an
70
orderly fashion, possibly merging them later. Also, on some systems,
71
large blocks are obtained via calls to mmap, so giving them back to
72
free system resources becomes most important.<br>
73
<br>
74
The function _S_should_i_give decides the policy that determines
75
whether the current block of memory should be given to the allocator
76
for the request that it has made. That's because we may not always have
77
exact fits for the memory size that the allocator requests. We do this
78
mainly to prevent external fragmentation at the cost of a little
79
internal fragmentation. Now, the value of this internal fragmentation
80
has to be decided by this function. I can see 3 possibilities right
81
now. Please add more as and when you find better strategies.<br>
82
<br>
83
<ol>
84
  <li>Equal size check. Return true only when the 2 blocks are of equal
85
size.</li>
86
  <li>Difference Threshold: Return true only when the _block_size is
87
greater than or equal to the _required_size, and if the _BS is &gt; _RS
88
by a difference of less than some THRESHOLD value, then return true,
89
else return false. </li>
90
  <li>Percentage Threshold. Return true only when the _block_size is
91
greater than or equal to the _required_size, and if the _BS is &gt; _RS
92
by a percentage of less than some THRESHOLD value, then return true,
93
else return false.</li>
94
</ol>
95
<br>
96
Currently, (3) is being used with a value of 36% Maximum wastage per
97
Super Block.<br>
98
<br>
99
<hr style="width: 100%; height: 2px;"><span style="font-weight: bold;">1)
100
What is a super block? Why is it needed?</span><br>
101
<br>
102
A super block is the block of memory acquired from the FLS from which
103
the bitmap allocator carves out memory for single objects and satisfies
104
the user's requests. These super blocks come in sizes that are powers
105
of 2 and multiples of 32 (_Bits_Per_Block). Yes both at the same time!
106
That's because the next super block acquired will be 2 times the
107
previous one, and also all super blocks have to be multiples of the
108
_Bits_Per_Block value. <br>
109
<br>
110
<span style="font-weight: bold;">2) How does it interact with the free
111
list store?</span><br>
112
<br>
113
The super block is contained in the FLS, and the FLS is responsible for
114
getting / returning Super Bocks to and from the OS using operator new
115
as defined by the C++ standard.<br>
116
<br>
117
<hr style="width: 100%; height: 2px;">
118
<h3 style="text-align: center;">How does the allocate function Work?</h3>
119
<br>
120
The allocate function is specialized for single object allocation ONLY.
121
Thus, ONLY if n == 1, will the bitmap_allocator's specialized algorithm
122
be used. Otherwise, the request is satisfied directly by calling
123
operator new.<br>
124
<br>
125
Suppose n == 1, then the allocator does the following:<br>
126
<br>
127
<ol>
128
  <li>Checks to see whether the a free block exists somewhere in a
129
region of memory close to the last satisfied request. If so, then that
130
block is marked as allocated in the bit map and given to the user. If
131
not, then (2) is executed.</li>
132
  <li>Is there a free block anywhere after the current block right upto
133
the end of the memory that we have? If so, that block is found, and the
134
same procedure is applied as above, and returned to the user. If not,
135
then (3) is executed.</li>
136
  <li>Is there any block in whatever region of memory that we own free?
137
This is done by checking <br>
138
    <div style="margin-left: 40px;">
139
    <ul>
140
      <li>The use count for each super block, and if that fails then </li>
141
      <li>The individual bit-maps for each super block. </li>
142
    </ul>
143
    </div>
144
Note: Here we are never touching any of the memory that the user will
145
be given, and we are confining all memory accesses to a small region of
146
memory! This helps reduce cache misses. If this succeeds then we apply
147
the same procedure on that bit-map as (1), and return that block of
148
memory to the user. However, if this process fails, then we resort to
149
(4).</li>
150
  <li>This process involves Refilling the internal exponentially
151
growing memory pool. The said effect is achieved by calling
152
_S_refill_pool which does the following: <br>
153
    <div style="margin-left: 40px;">
154
    <ul>
155
      <li>Gets more memory from the Global Free List of the Required
156
size. </li>
157
      <li>Adjusts the size for the next call to itself. </li>
158
      <li>Writes the appropriate headers in the bit-maps.</li>
159
      <li>Sets the use count for that super-block just allocated to 0
160
(zero). </li>
161
      <li>All of the above accounts to maintaining the basic invariant
162
for the allocator. If the invariant is maintained, we are sure that all
163
is well. Now, the same process is applied on the newly acquired free
164
blocks, which are dispatched accordingly.</li>
165
    </ul>
166
    </div>
167
  </li>
168
</ol>
169
<br>
170
Thus, you can clearly see that the allocate function is nothing but a
171
combination of the next-fit and first-fit algorithm optimized ONLY for
172
single object allocations.<br>
173
<br>
174
<br>
175
<hr style="width: 100%; height: 2px;">
176
<h3 style="text-align: center;">How does the deallocate function work?</h3>
177
<br>
178
The deallocate function again is specialized for single objects ONLY.
179
For all n belonging to &gt; 1, the operator delete is called without
180
further ado, and the deallocate function returns.<br>
181
<br>
182
However for n == 1, a series of steps are performed:<br>
183
<br>
184
<ol>
185
  <li>We first need to locate that super-block which holds the memory
186
location given to us by the user. For that purpose, we maintain a
187
static variable _S_last_dealloc_index, which holds the index into the
188
vector of block pairs which indicates the index of the last super-block
189
from which memory was freed. We use this strategy in the hope that the
190
user will deallocate memory in a region close to what he/she
191
deallocated the last time around. If the check for belongs_to succeeds,
192
then we determine the bit-map for the given pointer, and locate the
193
index into that bit-map, and mark that bit as free by setting it.</li>
194
  <li>If the _S_last_dealloc_index does not point to the memory block
195
that we're looking for, then we do a linear search on the block stored
196
in the vector of Block Pairs. This vector in code is called
197
_S_mem_blocks. When the corresponding super-block is found, we apply
198
the same procedure as we did for (1) to mark the block as free in the
199
bit-map.</li>
200
</ol>
201
<br>
202
Now, whenever a block is freed, the use count of that particular super
203
block goes down by 1. When this use count hits 0, we remove that super
204
block from the list of all valid super blocks stored in the vector.
205
While doing this, we also make sure that the basic invariant is
206
maintained by making sure that _S_last_request and
207
_S_last_dealloc_index point to valid locations within the vector.<br>
208
<br>
209
<hr style="width: 100%; height: 2px;"><br>
210
<h3 style="text-align: center;">Data Layout for a Super Block:</h3>
211
<br>
212
Each Super Block will be of some size that is a multiple of the number
213
of Bits Per Block. Typically, this value is chosen as Bits_Per_Byte x
214
sizeof(size_t). On an x86 system, this gives the figure &nbsp;8 x
215
4 = 32. Thus, each Super Block will be of size 32 x Some_Value. This
216
Some_Value is sizeof(value_type). For now, let it be called 'K'. Thus,
217
finally, Super Block size is 32 x K bytes.<br>
218
<br>
219
This value of 32 has been chosen because each size_t has 32-bits
220
and Maximum use of these can be made with such a figure.<br>
221
<br>
222
Consider a block of size 64 ints. In memory, it would look like this:
223
(assume a 32-bit system where, size_t is a 32-bit entity).<br>
224
<br>
225
<table cellpadding="0" cellspacing="0" border="1"
226
 style="text-align: left; width: 763px; height: 21px;">
227
  <tbody>
228
    <tr>
229
      <td style="vertical-align: top; text-align: center;">268<br>
230
      </td>
231
      <td style="vertical-align: top; text-align: center;">0<br>
232
      </td>
233
      <td style="vertical-align: top; text-align: center;">4294967295<br>
234
      </td>
235
      <td style="vertical-align: top; text-align: center;">4294967295<br>
236
      </td>
237
      <td style="vertical-align: top; text-align: center;">Data -&gt;
238
Space for 64 ints<br>
239
      </td>
240
    </tr>
241
  </tbody>
242
</table>
243
<br>
244
<br>
245
The first Column(268) represents the size of the Block in bytes as seen
246
by
247
the Bitmap Allocator. Internally, a global free list is used to keep
248
track of the free blocks used and given back by the bitmap allocator.
249
It is this Free List Store that is responsible for writing and managing
250
this information. Actually the number of bytes allocated in this case
251
would be: 4 + 4 + (4x2) + (64x4) = 272 bytes, but the first 4 bytes are
252
an
253
addition by the Free List Store, so the Bitmap Allocator sees only 268
254
bytes. These first 4 bytes about which the bitmapped allocator is not
255
aware hold the value 268.<br>
256
<br>
257
<span style="font-weight: bold;">What do the remaining values represent?</span><br>
258
<br>
259
The 2nd 4 in the expression is the sizeof(size_t) because the
260
Bitmapped Allocator maintains a used count for each Super Block, which
261
is initially set to 0 (as indicated in the diagram). This is
262
incremented every time a block is removed from this super block
263
(allocated), and decremented whenever it is given back. So, when the
264
used count falls to 0, the whole super block will be given back to the
265
Free List Store.<br>
266
<br>
267
The value 4294967295 represents the integer corresponding to the bit
268
representation of all bits set: 11111111111111111111111111111111.<br>
269
<br>
270
The 3rd 4x2 is size of the bitmap itself, which is the size of 32-bits
271
x 2,
272
which is 8-bytes, or 2 x sizeof(size_t).<br>
273
<br>
274
<hr style="width: 100%; height: 2px;"><br>
275
Another issue would be whether to keep the all bitmaps in a separate
276
area in memory, or to keep them near the actual blocks that will be
277
given out or allocated for the client. After some testing, I've decided
278
to keep these bitmaps close to the actual blocks. this will help in 2
279
ways. <br>
280
<br>
281
<ol>
282
  <li>Constant time access for the bitmap themselves, since no kind of
283
look up will be needed to find the correct bitmap list or it's
284
equivalent.</li>
285
  <li>And also this would preserve the cache as far as possible.</li>
286
</ol>
287
<br>
288
So in effect, this kind of an allocator might prove beneficial from a
289
purely cache point of view. But this allocator has been made to try and
290
roll out the defects of the node_allocator, wherein the nodes get
291
skewed about in memory, if they are not returned in the exact reverse
292
order or in the same order in which they were allocated. Also, the
293
new_allocator's book keeping overhead is too much for small objects and
294
single object allocations, though it preserves the locality of blocks
295
very well when they are returned back to the allocator.<br>
296
<br>
297
<hr style="width: 100%; height: 2px;"><br>
298
Expected overhead per block would be 1 bit in memory. Also, once the
299
address of the free list has been found, the cost for
300
allocation/deallocation would be negligible, and is supposed to be
301
constant time. For these very reasons, it is very important to minimize
302
the linear time costs, which include finding a free list with a free
303
block while allocating, and finding the corresponding free list for a
304
block while deallocating. Therefore, I have decided that the growth of
305
the internal pool for this allocator will be exponential as compared to
306
linear for node_allocator. There, linear time works well, because we
307
are mainly concerned with speed of allocation/deallocation and memory
308
consumption, whereas here, the allocation/deallocation part does have
309
some linear/logarithmic complexity components in it. Thus, to try and
310
minimize them would be a good thing to do at the cost of a little bit
311
of memory.<br>
312
<br>
313
Another thing to be noted is the the pool size will double every time
314
the internal pool gets exhausted, and all the free blocks have been
315
given away. The initial size of the pool would be sizeof(size_t) x 8
316
which is the number of bits in an integer, which can fit exactly
317
in a CPU register. Hence, the term given is exponential growth of the
318
internal pool.<br>
319
<br>
320
<hr style="width: 100%; height: 2px;">After reading all this, you may
321
still have a few questions about the internal working of this
322
allocator, like my friend had!<br>
323
<br>
324
Well here are the exact questions that he posed:<br>
325
<br>
326
<span style="font-weight: bold;">Q1) The "Data Layout" section is
327
cryptic. I have no idea of what you are trying to say. Layout of what?
328
The free-list? Each bitmap? The Super Block?</span><br>
329
<br>
330
<div style="margin-left: 40px;"> The layout of a Super Block of a given
331
size. In the example, a super block of size 32 x 1 is taken. The
332
general formula for calculating the size of a super block is
333
32 x sizeof(value_type) x 2^n, where n ranges from 0 to 32 for 32-bit
334
systems.<br>
335
</div>
336
<br>
337
<span style="font-weight: bold;">Q2) And since I just mentioned the
338
term `each bitmap', what in the world is meant by it? What does each
339
bitmap manage? How does it relate to the super block? Is the Super
340
Block a bitmap as well?</span><br style="font-weight: bold;">
341
<br>
342
<div style="margin-left: 40px;"> Good question! Each bitmap is part of
343
a
344
Super Block which is made up of 3 parts as I have mentioned earlier.
345
Re-iterating, 1. The use count, 2. The bit-map for that Super Block. 3.
346
The actual memory that will be eventually given to the user. Each
347
bitmap is a multiple of 32 in size. If there are 32 x (2^3) blocks of
348
single objects to be given, there will be '32 x (2^3)' bits present.
349
Each
350
32 bits managing the allocated / free status for 32 blocks. Since each
351
size_t contains 32-bits, one size_t can manage upto 32
352
blocks' status. Each bit-map is made up of a number of size_t,
353
whose exact number for a super-block of a given size I have just
354
mentioned.<br>
355
</div>
356
<br>
357
<span style="font-weight: bold;">Q3) How do the allocate and deallocate
358
functions work in regard to bitmaps?</span><br>
359
<br>
360
<div style="margin-left: 40px;"> The allocate and deallocate functions
361
manipulate the bitmaps and have nothing to do with the memory that is
362
given to the user. As I have earlier mentioned, a 1 in the bitmap's bit
363
field indicates free, while a 0 indicates allocated. This lets us check
364
32 bits at a time to check whether there is at lease one free block in
365
those 32 blocks by testing for equality with (0). Now, the allocate
366
function will given a memory block find the corresponding bit in the
367
bitmap, and will reset it (ie. make it re-set (0)). And when the
368
deallocate function is called, it will again set that bit after
369
locating it to indicate that that particular block corresponding to
370
this bit in the bit-map is not being used by anyone, and may be used to
371
satisfy future requests.<br>
372
<br>
373
eg: Consider a bit-map of 64-bits as represented below:<br>
374
1111111111111111111111111111111111111111111111111111111111111111<br>
375
<br>
376
Now, when the first request for allocation of a single object comes
377
along, the first block in address order is returned. And since the
378
bit-maps in the reverse order to that of the address order, the last
379
bit(LSB if the bit-map is considered as a binary word of 64-bits) is
380
re-set to 0.<br>
381
<br>
382
The bit-map now looks like this:<br>
383
1111111111111111111111111111111111111111111111111111111111111110<br>
384
</div>
385
<br>
386
<br>
387
<hr style="width: 100%; height: 2px;"><br>
388
(Tech-Stuff, Please stay out if you are not interested in the selection
389
of certain constants. This has nothing to do with the algorithm per-se,
390
only with some vales that must be chosen correctly to ensure that the
391
allocator performs well in a real word scenario, and maintains a good
392
balance between the memory consumption and the allocation/deallocation
393
speed).<br>
394
<br>
395
The formula for calculating the maximum wastage as a percentage:<br>
396
<br>
397
(32 x k + 1) / (2 x (32 x k + 1 + 32 x c)) x 100.<br>
398
<br>
399
Where,<br>
400
k =&gt; The constant overhead per node. eg. for list, it is 8 bytes,
401
and for map it is 12 bytes.<br>
402
c =&gt; The size of the base type on which the map/list is
403
instantiated. Thus, suppose the the type1 is int and type2 is double,
404
they are related by the relation sizeof(double) == 2*sizeof(int). Thus,
405
all types must have this double size relation for this formula to work
406
properly.<br>
407
<br>
408
Plugging-in: For List: k = 8 and c = 4 (int and double), we get:<br>
409
33.376%<br>
410
<br>
411
For map/multimap: k = 12, and c = 4 (int and double), we get:<br>
412
37.524%<br>
413
<br>
414
Thus, knowing these values, and based on the sizeof(value_type), we may
415
create a function that returns the Max_Wastage_Percentage for us to use.<br>
416
<br>
417
<hr style="width: 100%; height: 2px;"><small><small><em> See <a
418
 href="file:///home/dhruv/projects/libstdc++-v3/gcc/libstdc++-v3/docs/html/17_intro/license.html">license.html</a>
419
for copying conditions. Comments and suggestions are welcome, and may
420
be
421
sent to <a href="mailto:libstdc++@gcc.gnu.org">the libstdc++ mailing
422
list</a>.</em><br>
423
</small></small><br>
424
<br>
425
</body>
426
</html>

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.