CS 481: Assignment #4 Solutions

First problem: Problem 14 in Chapter 10 (p. 427 of the text).

What we are given is rather vague, so the answers are necessarily rather superficial. In allocating a block of size 256k, an overhead of 8 bytes is vanishingly small: 2^3 over 2^18, so about 2^-15, or around .003%. In allocating a block of size 40, the same overhead of 8 bytes now translates into 8/48 or about 17%. Of course, there is other space overhead: a binary buddy system would lose about 25% to internal fragmentation and some more (perhaps 5%) to external fragmentation; a boundary-tag system would lose some 10-20% to external fragmentation. The time overhead is hard to gauge: buddy methods take about the same amount of time to allocate a small block as to allocate a large one, but boundary tag methods tend to take longer for larger blocks, because they are rarer and thus necessitate a longer search. The times given are essentially meaningless---they may be fairly realistic, but their values require some gauge against which to evaluate them.

Second problem: Buddy allocation systems work on a very general principle -- they are not limited to powers of two. The fundamental idea is a recurrence relation: if you cannot find a block of the appropriate size, you grab a larger block, then cut it into smaller pieces and recursively attempt to allocate from one of the smaller pieces. The binary buddy system takes a piece and cuts it into two equal subpieces; a ternary buddy could cut the large piece into three equal subpieces and thus would have sizes that would grow as powers of 3. More complex buddy systems in common use cut a large piece into unequal pieces; the most common is the Fibonacci buddy system: given a block on ``shelf'' n, it cuts it into two blocks, one for shelf n-1 and one for shelf n-2. The result is that its pieces have sizes that are powers of the golden ratio (approximately 1.62); the Fibonacci buddy system thus offers a larger selection of sizes than the binary buddy system.

For a buddy system that cuts a piece into two (not necessarily equal) pieces, the general recurrence describing block sizes is f(n)=f(n-1)+f(n-k), where k is a strictly positive integer.

  • Why is the first term always f(n-1)?

    Quite simply, if the top shelf piece is cut and none of the resulting piece goes on the shelf right below, that shelf will remain empty forever---it mioght as well not be counted in the shelf system. In other words, this is just a relative counting scheme---for instance, notice that we cannot distinguish the effects of f(n)=2*f(n-2) from those of f(n)=2*f(n-1): in both cases, the piece is split into 2 equal parts and thus the shelves correspond to powers of two.

  • The larger k is, the more pronounced the difference in sizes between the two pieces; why is k=2 a common choice, yet larger values are never used?

    Because a greater disparity between the two pieces could easily create unusably small pieces and because the inventory would grow too much.

  • Discuss how you would implement the Fibonacci buddy system (k=2); the main point is how you would decide which blocks to merge when they are freed.

    The trick is to make sure that, when we merge a block with its buddy, we can reconstitute for the merged result the same tpye of information that was carried in the two merged blocks and that had allowed us to realize that they were buddies. Each block will carry a free/busy bit, a shelf number, and a left/right bit (which we can think of as smaller/larger); in addition, each block will have one more bit, reserved for inheritance. When we split a block, the two bits (L/R and inheritance) are apportioned to the two "children" (the two smaller blocks resulting from the split: the left child gets the L/R bit of the parent and the right child gets the inheritance bit of the parent; in addition, of course, the L/R bit of the left child is set to L and that of the right child to R. When we merge two buddies, the two bits of the parent are the inheritance bits of the two buddies: that of the left buddy becomes the L/R bit of the parent and that of that right buddy becomes the inheritance bit of the parent.

    With this system, all necessary information is available in each block with a fixed number of bits---it would be unacceptable to require larger and larger amount of bits as the block got split further and further. With this scheme, we can find our buddy by checking our own L/R bit and looking up the appropriate shelf for the matching buddy's size, then computing its address (by adding or subtracting the size from our address) and checking at that address to see if the block is free and of the right size (from the right shelf).

    Deciding which shelf to search is done by binary search among the shelves. In no case (allocation and deallocation) is the golden ratio used directly---too complicated and too prone to numerical errors.

  • Back to CS 481 home page