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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libstdc++-v3/] [doc/] [html/] [manual/] [bk01pt03ch21s02.html] - Blame information for rev 742

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 742 jeremybenn
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
3
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Implementation</title><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"/><meta name="keywords" content="&#10;      ISO C++&#10;    , &#10;      allocator&#10;    "/><meta name="keywords" content="&#10;      ISO C++&#10;    , &#10;      library&#10;    "/><meta name="keywords" content="&#10;      ISO C++&#10;    , &#10;      runtime&#10;    , &#10;      library&#10;    "/><link rel="home" href="../index.html" title="The GNU C++ Library"/><link rel="up" href="bitmap_allocator.html" title="Chapter 21. The bitmap_allocator"/><link rel="prev" href="bitmap_allocator.html" title="Chapter 21. The bitmap_allocator"/><link rel="next" href="policy_data_structures.html" title="Chapter 22. Policy-Based Data Structures"/></head><body><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Implementation</th></tr><tr><td align="left"><a accesskey="p" href="bitmap_allocator.html">Prev</a> </td><th width="60%" align="center">Chapter 21. The bitmap_allocator</th><td align="right"> <a accesskey="n" href="policy_data_structures.html">Next</a></td></tr></table><hr/></div><div class="section" title="Implementation"><div class="titlepage"><div><div><h2 class="title"><a id="allocator.bitmap.impl"/>Implementation</h2></div></div></div><div class="section" title="Free List Store"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.free_list_store"/>Free List Store</h3></div></div></div><p>
4
    The Free List Store (referred to as FLS for the remaining part of this
5
    document) is the Global memory pool that is shared by all instances of
6
    the bitmapped allocator instantiated for any type. This maintains a
7
    sorted order of all free memory blocks given back to it by the
8
    bitmapped allocator, and is also responsible for giving memory to the
9
    bitmapped allocator when it asks for more.
10
  </p><p>
11
    Internally, there is a Free List threshold which indicates the
12
    Maximum number of free lists that the FLS can hold internally
13
    (cache).  Currently, this value is set at 64. So, if there are
14
    more than 64 free lists coming in, then some of them will be given
15
    back to the OS using operator delete so that at any given time the
16
    Free List's size does not exceed 64 entries. This is done because
17
    a Binary Search is used to locate an entry in a free list when a
18
    request for memory comes along.  Thus, the run-time complexity of
19
    the search would go up given an increasing size, for 64 entries
20
    however, lg(64) == 6 comparisons are enough to locate the correct
21
    free list if it exists.
22
  </p><p>
23
    Suppose the free list size has reached its threshold, then the
24
    largest block from among those in the list and the new block will
25
    be selected and given back to the OS. This is done because it
26
    reduces external fragmentation, and allows the OS to use the
27
    larger blocks later in an orderly fashion, possibly merging them
28
    later. Also, on some systems, large blocks are obtained via calls
29
    to mmap, so giving them back to free system resources becomes most
30
    important.
31
  </p><p>
32
    The function _S_should_i_give decides the policy that determines
33
    whether the current block of memory should be given to the
34
    allocator for the request that it has made. That's because we may
35
    not always have exact fits for the memory size that the allocator
36
    requests. We do this mainly to prevent external fragmentation at
37
    the cost of a little internal fragmentation. Now, the value of
38
    this internal fragmentation has to be decided by this function. I
39
    can see 3 possibilities right now. Please add more as and when you
40
    find better strategies.
41
  </p><div class="orderedlist"><ol class="orderedlist"><li class="listitem"><p>Equal size check. Return true only when the 2 blocks are of equal
42
size.</p></li><li class="listitem"><p>Difference Threshold: Return true only when the _block_size is
43
greater than or equal to the _required_size, and if the _BS is &gt; _RS
44
by a difference of less than some THRESHOLD value, then return true,
45
else return false. </p></li><li class="listitem"><p>Percentage Threshold. Return true only when the _block_size is
46
greater than or equal to the _required_size, and if the _BS is &gt; _RS
47
by a percentage of less than some THRESHOLD value, then return true,
48
else return false.</p></li></ol></div><p>
49
    Currently, (3) is being used with a value of 36% Maximum wastage per
50
    Super Block.
51
  </p></div><div class="section" title="Super Block"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.super_block"/>Super Block</h3></div></div></div><p>
52
    A super block is the block of memory acquired from the FLS from
53
    which the bitmap allocator carves out memory for single objects
54
    and satisfies the user's requests. These super blocks come in
55
    sizes that are powers of 2 and multiples of 32
56
    (_Bits_Per_Block). Yes both at the same time!  That's because the
57
    next super block acquired will be 2 times the previous one, and
58
    also all super blocks have to be multiples of the _Bits_Per_Block
59
    value.
60
  </p><p>
61
    How does it interact with the free list store?
62
  </p><p>
63
    The super block is contained in the FLS, and the FLS is responsible for
64
    getting / returning Super Bocks to and from the OS using operator new
65
    as defined by the C++ standard.
66
  </p></div><div class="section" title="Super Block Data Layout"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.super_block_data"/>Super Block Data Layout</h3></div></div></div><p>
67
    Each Super Block will be of some size that is a multiple of the
68
    number of Bits Per Block. Typically, this value is chosen as
69
    Bits_Per_Byte x sizeof(size_t). On an x86 system, this gives the
70
    figure 8 x 4 = 32. Thus, each Super Block will be of size 32
71
    x Some_Value. This Some_Value is sizeof(value_type). For now, let
72
    it be called 'K'. Thus, finally, Super Block size is 32 x K bytes.
73
  </p><p>
74
    This value of 32 has been chosen because each size_t has 32-bits
75
    and Maximum use of these can be made with such a figure.
76
  </p><p>
77
    Consider a block of size 64 ints. In memory, it would look like this:
78
    (assume a 32-bit system where, size_t is a 32-bit entity).
79
  </p><div class="table"><a id="id515279"/><p class="title"><strong>Table 21.1. Bitmap Allocator Memory Map</strong></p><div class="table-contents"><table summary="Bitmap Allocator Memory Map" border="1"><colgroup><col style="text-align: left" class="c1"/><col style="text-align: left" class="c2"/><col style="text-align: left" class="c3"/><col style="text-align: left" class="c4"/><col style="text-align: left" class="c5"/></colgroup><tbody><tr><td style="text-align: left">268</td><td style="text-align: left">0</td><td style="text-align: left">4294967295</td><td style="text-align: left">4294967295</td><td style="text-align: left">Data -&gt; Space for 64 ints</td></tr></tbody></table></div></div><br class="table-break"/><p>
80
    The first Column(268) represents the size of the Block in bytes as
81
    seen by the Bitmap Allocator. Internally, a global free list is
82
    used to keep track of the free blocks used and given back by the
83
    bitmap allocator.  It is this Free List Store that is responsible
84
    for writing and managing this information. Actually the number of
85
    bytes allocated in this case would be: 4 + 4 + (4x2) + (64x4) =
86
    272 bytes, but the first 4 bytes are an addition by the Free List
87
    Store, so the Bitmap Allocator sees only 268 bytes. These first 4
88
    bytes about which the bitmapped allocator is not aware hold the
89
    value 268.
90
  </p><p>
91
  What do the remaining values represent?</p><p>
92
    The 2nd 4 in the expression is the sizeof(size_t) because the
93
    Bitmapped Allocator maintains a used count for each Super Block,
94
    which is initially set to 0 (as indicated in the diagram). This is
95
    incremented every time a block is removed from this super block
96
    (allocated), and decremented whenever it is given back. So, when
97
    the used count falls to 0, the whole super block will be given
98
    back to the Free List Store.
99
  </p><p>
100
    The value 4294967295 represents the integer corresponding to the bit
101
    representation of all bits set: 11111111111111111111111111111111.
102
  </p><p>
103
    The 3rd 4x2 is size of the bitmap itself, which is the size of 32-bits
104
    x 2,
105
    which is 8-bytes, or 2 x sizeof(size_t).
106
  </p></div><div class="section" title="Maximum Wasted Percentage"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.max_wasted"/>Maximum Wasted Percentage</h3></div></div></div><p>
107
    This has nothing to do with the algorithm per-se,
108
    only with some vales that must be chosen correctly to ensure that the
109
    allocator performs well in a real word scenario, and maintains a good
110
    balance between the memory consumption and the allocation/deallocation
111
    speed.
112
  </p><p>
113
    The formula for calculating the maximum wastage as a percentage:
114
  </p><p>
115
(32 x k + 1) / (2 x (32 x k + 1 + 32 x c)) x 100.
116
  </p><p>
117
    where k is the constant overhead per node (e.g., for list, it is
118
    8 bytes, and for map it is 12 bytes) and c is the size of the
119
    base type on which the map/list is instantiated. Thus, suppose the
120
    type1 is int and type2 is double, they are related by the relation
121
    sizeof(double) == 2*sizeof(int). Thus, all types must have this
122
    double size relation for this formula to work properly.
123
  </p><p>
124
    Plugging-in: For List: k = 8 and c = 4 (int and double), we get:
125
    33.376%
126
  </p><p>
127
For map/multimap: k = 12, and c = 4 (int and double), we get: 37.524%
128
  </p><p>
129
    Thus, knowing these values, and based on the sizeof(value_type), we may
130
    create a function that returns the Max_Wastage_Percentage for us to use.
131
  </p></div><div class="section" title="allocate"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.allocate"/><code class="function">allocate</code></h3></div></div></div><p>
132
    The allocate function is specialized for single object allocation
133
    ONLY.  Thus, ONLY if n == 1, will the bitmap_allocator's
134
    specialized algorithm be used. Otherwise, the request is satisfied
135
    directly by calling operator new.
136
  </p><p>
137
    Suppose n == 1, then the allocator does the following:
138
  </p><div class="orderedlist"><ol class="orderedlist"><li class="listitem"><p>
139
        Checks to see whether a free block exists somewhere in a region
140
        of memory close to the last satisfied request. If so, then that
141
        block is marked as allocated in the bit map and given to the
142
        user. If not, then (2) is executed.
143
    </p></li><li class="listitem"><p>
144
        Is there a free block anywhere after the current block right
145
        up to the end of the memory that we have? If so, that block is
146
        found, and the same procedure is applied as above, and
147
        returned to the user. If not, then (3) is executed.
148
    </p></li><li class="listitem"><p>
149
        Is there any block in whatever region of memory that we own
150
        free?  This is done by checking
151
      </p><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem"><p>
152
        The use count for each super block, and if that fails then
153
        </p></li><li class="listitem"><p>
154
          The individual bit-maps for each super block.
155
        </p></li></ul></div><p>
156
        Note: Here we are never touching any of the memory that the
157
        user will be given, and we are confining all memory accesses
158
        to a small region of memory! This helps reduce cache
159
        misses. If this succeeds then we apply the same procedure on
160
        that bit-map as (1), and return that block of memory to the
161
        user. However, if this process fails, then we resort to (4).
162
        </p></li><li class="listitem"><p>
163
        This process involves Refilling the internal exponentially
164
        growing memory pool. The said effect is achieved by calling
165
        _S_refill_pool which does the following:
166
      </p><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem"><p>
167
            Gets more memory from the Global Free List of the Required
168
            size.
169
          </p></li><li class="listitem"><p>
170
      Adjusts the size for the next call to itself.
171
      </p></li><li class="listitem"><p>
172
      Writes the appropriate headers in the bit-maps.
173
      </p></li><li class="listitem"><p>
174
        Sets the use count for that super-block just allocated to 0
175
        (zero).
176
      </p></li><li class="listitem"><p>
177
          All of the above accounts to maintaining the basic invariant
178
          for the allocator. If the invariant is maintained, we are
179
          sure that all is well. Now, the same process is applied on
180
          the newly acquired free blocks, which are dispatched
181
          accordingly.
182
      </p></li></ul></div></li></ol></div><p>
183
Thus, you can clearly see that the allocate function is nothing but a
184
combination of the next-fit and first-fit algorithm optimized ONLY for
185
single object allocations.
186
</p></div><div class="section" title="deallocate"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.deallocate"/><code class="function">deallocate</code></h3></div></div></div><p>
187
    The deallocate function again is specialized for single objects ONLY.
188
    For all n belonging to &gt; 1, the operator delete is called without
189
    further ado, and the deallocate function returns.
190
  </p><p>
191
    However for n == 1, a series of steps are performed:
192
  </p><div class="orderedlist"><ol class="orderedlist"><li class="listitem"><p>
193
      We first need to locate that super-block which holds the memory
194
      location given to us by the user. For that purpose, we maintain
195
      a static variable _S_last_dealloc_index, which holds the index
196
      into the vector of block pairs which indicates the index of the
197
      last super-block from which memory was freed. We use this
198
      strategy in the hope that the user will deallocate memory in a
199
      region close to what he/she deallocated the last time around. If
200
      the check for belongs_to succeeds, then we determine the bit-map
201
      for the given pointer, and locate the index into that bit-map,
202
      and mark that bit as free by setting it.
203
    </p></li><li class="listitem"><p>
204
      If the _S_last_dealloc_index does not point to the memory block
205
      that we're looking for, then we do a linear search on the block
206
      stored in the vector of Block Pairs. This vector in code is
207
      called _S_mem_blocks. When the corresponding super-block is
208
      found, we apply the same procedure as we did for (1) to mark the
209
      block as free in the bit-map.
210
    </p></li></ol></div><p>
211
    Now, whenever a block is freed, the use count of that particular
212
    super block goes down by 1. When this use count hits 0, we remove
213
    that super block from the list of all valid super blocks stored in
214
    the vector.  While doing this, we also make sure that the basic
215
    invariant is maintained by making sure that _S_last_request and
216
    _S_last_dealloc_index point to valid locations within the vector.
217
  </p></div><div class="section" title="Questions"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.questions"/>Questions</h3></div></div></div><div class="section" title="1"><div class="titlepage"><div><div><h4 class="title"><a id="bitmap.impl.question.1"/>1</h4></div></div></div><p>
218
Q1) The "Data Layout" section is
219
cryptic. I have no idea of what you are trying to say. Layout of what?
220
The free-list? Each bitmap? The Super Block?
221
    </p><p>
222
      The layout of a Super Block of a given
223
size. In the example, a super block of size 32 x 1 is taken. The
224
general formula for calculating the size of a super block is
225
32 x sizeof(value_type) x 2^n, where n ranges from 0 to 32 for 32-bit
226
systems.
227
    </p></div><div class="section" title="2"><div class="titlepage"><div><div><h4 class="title"><a id="bitmap.impl.question.2"/>2</h4></div></div></div><p>
228
      And since I just mentioned the
229
term `each bitmap', what in the world is meant by it? What does each
230
bitmap manage? How does it relate to the super block? Is the Super
231
Block a bitmap as well?
232
    </p><p>
233
      Each bitmap is part of a Super Block which is made up of 3 parts
234
      as I have mentioned earlier.  Re-iterating, 1. The use count,
235
      2. The bit-map for that Super Block. 3.  The actual memory that
236
      will be eventually given to the user. Each bitmap is a multiple
237
      of 32 in size. If there are 32 x (2^3) blocks of single objects
238
      to be given, there will be '32 x (2^3)' bits present.  Each 32
239
      bits managing the allocated / free status for 32 blocks. Since
240
      each size_t contains 32-bits, one size_t can manage up to 32
241
      blocks' status. Each bit-map is made up of a number of size_t,
242
      whose exact number for a super-block of a given size I have just
243
      mentioned.
244
    </p></div><div class="section" title="3"><div class="titlepage"><div><div><h4 class="title"><a id="bitmap.impl.question.3"/>3</h4></div></div></div><p>
245
      How do the allocate and deallocate functions work in regard to
246
      bitmaps?
247
    </p><p>
248
      The allocate and deallocate functions manipulate the bitmaps and
249
      have nothing to do with the memory that is given to the user. As
250
      I have earlier mentioned, a 1 in the bitmap's bit field
251
      indicates free, while a 0 indicates allocated. This lets us
252
      check 32 bits at a time to check whether there is at lease one
253
      free block in those 32 blocks by testing for equality with
254
      (0). Now, the allocate function will given a memory block find
255
      the corresponding bit in the bitmap, and will reset it (i.e.,
256
      make it re-set (0)). And when the deallocate function is called,
257
      it will again set that bit after locating it to indicate that
258
      that particular block corresponding to this bit in the bit-map
259
      is not being used by anyone, and may be used to satisfy future
260
      requests.
261
    </p><p>
262
      e.g.: Consider a bit-map of 64-bits as represented below:
263
      1111111111111111111111111111111111111111111111111111111111111111
264
    </p><p>
265
      Now, when the first request for allocation of a single object
266
      comes along, the first block in address order is returned. And
267
      since the bit-maps in the reverse order to that of the address
268
      order, the last bit (LSB if the bit-map is considered as a
269
      binary word of 64-bits) is re-set to 0.
270
    </p><p>
271
      The bit-map now looks like this:
272
      1111111111111111111111111111111111111111111111111111111111111110
273
    </p></div></div><div class="section" title="Locality"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.locality"/>Locality</h3></div></div></div><p>
274
    Another issue would be whether to keep the all bitmaps in a
275
    separate area in memory, or to keep them near the actual blocks
276
    that will be given out or allocated for the client. After some
277
    testing, I've decided to keep these bitmaps close to the actual
278
    blocks. This will help in 2 ways.
279
  </p><div class="orderedlist"><ol class="orderedlist"><li class="listitem"><p>Constant time access for the bitmap themselves, since no kind of
280
look up will be needed to find the correct bitmap list or its
281
equivalent.</p></li><li class="listitem"><p>And also this would preserve the cache as far as possible.</p></li></ol></div><p>
282
    So in effect, this kind of an allocator might prove beneficial from a
283
    purely cache point of view. But this allocator has been made to try and
284
    roll out the defects of the node_allocator, wherein the nodes get
285
    skewed about in memory, if they are not returned in the exact reverse
286
    order or in the same order in which they were allocated. Also, the
287
    new_allocator's book keeping overhead is too much for small objects and
288
    single object allocations, though it preserves the locality of blocks
289
    very well when they are returned back to the allocator.
290
  </p></div><div class="section" title="Overhead and Grow Policy"><div class="titlepage"><div><div><h3 class="title"><a id="bitmap.impl.grow_policy"/>Overhead and Grow Policy</h3></div></div></div><p>
291
    Expected overhead per block would be 1 bit in memory. Also, once
292
    the address of the free list has been found, the cost for
293
    allocation/deallocation would be negligible, and is supposed to be
294
    constant time. For these very reasons, it is very important to
295
    minimize the linear time costs, which include finding a free list
296
    with a free block while allocating, and finding the corresponding
297
    free list for a block while deallocating. Therefore, I have
298
    decided that the growth of the internal pool for this allocator
299
    will be exponential as compared to linear for
300
    node_allocator. There, linear time works well, because we are
301
    mainly concerned with speed of allocation/deallocation and memory
302
    consumption, whereas here, the allocation/deallocation part does
303
    have some linear/logarithmic complexity components in it. Thus, to
304
    try and minimize them would be a good thing to do at the cost of a
305
    little bit of memory.
306
  </p><p>
307
    Another thing to be noted is the pool size will double every time
308
    the internal pool gets exhausted, and all the free blocks have
309
    been given away. The initial size of the pool would be
310
    sizeof(size_t) x 8 which is the number of bits in an integer,
311
    which can fit exactly in a CPU register. Hence, the term given is
312
    exponential growth of the internal pool.
313
  </p></div></div><div class="navfooter"><hr/><table width="100%" summary="Navigation footer"><tr><td align="left"><a accesskey="p" href="bitmap_allocator.html">Prev</a> </td><td align="center"><a accesskey="u" href="bitmap_allocator.html">Up</a></td><td align="right"> <a accesskey="n" href="policy_data_structures.html">Next</a></td></tr><tr><td align="left" valign="top">Chapter 21. The bitmap_allocator </td><td align="center"><a accesskey="h" href="../index.html">Home</a></td><td align="right" valign="top"> Chapter 22. Policy-Based Data Structures</td></tr></table></div></body></html>

powered by: WebSVN 2.1.0

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