0
0
Operating-systemsComparisonBeginner · 4 min read

Internal vs External Fragmentation: Key Differences and Usage

In operating systems, internal fragmentation happens when fixed-size memory blocks waste space inside allocated areas, while external fragmentation occurs when free memory is split into small scattered pieces outside allocated blocks. Both reduce usable memory but differ in cause and handling.
⚖️

Quick Comparison

This table summarizes the main differences between internal and external fragmentation.

AspectInternal FragmentationExternal Fragmentation
CauseFixed-size memory allocation wastes unused space inside blocksFree memory is split into small scattered holes outside allocated blocks
Memory Waste LocationInside allocated memory blocksBetween allocated memory blocks
DetectionEasy to detect by comparing allocated block size and requested sizeHarder to detect due to scattered free spaces
Effect on AllocationWastes space but allocation is simple and fastCan prevent allocation despite enough total free memory
SolutionUse smaller block sizes or variable-sized allocationMemory compaction or better allocation algorithms
ExampleAllocating 100 bytes in a 128-byte block wastes 28 bytesFree blocks of 20 and 30 bytes scattered prevent allocating 40 bytes
⚖️

Key Differences

Internal fragmentation occurs when memory is divided into fixed-size blocks, and a process requests less memory than the block size. The leftover space inside the block remains unused but reserved, causing wasted memory inside allocated blocks. This is common in systems using fixed partitioning or paging with fixed frame sizes.

On the other hand, external fragmentation happens when free memory is broken into small, non-contiguous chunks scattered between allocated blocks. Even if the total free memory is enough for a request, the scattered nature prevents allocation. This is typical in systems using variable-sized memory allocation.

While internal fragmentation wastes memory inside blocks, external fragmentation wastes memory outside allocated blocks, making it harder to manage. Internal fragmentation is easier to handle by adjusting block sizes, but external fragmentation often requires memory compaction or advanced allocation strategies.

⚖️

Code Comparison

This example shows a simple fixed-size block allocator that can cause internal fragmentation.

python
class FixedBlockAllocator:
    def __init__(self, block_size, total_blocks):
        self.block_size = block_size
        self.total_blocks = total_blocks
        self.memory = [None] * total_blocks

    def allocate(self, size):
        if size > self.block_size:
            return -1  # Cannot allocate
        for i in range(self.total_blocks):
            if self.memory[i] is None:
                self.memory[i] = size  # Store requested size
                return i  # Return block index
        return -1  # No free block

    def free(self, index):
        if 0 <= index < self.total_blocks:
            self.memory[index] = None

allocator = FixedBlockAllocator(block_size=128, total_blocks=5)
block1 = allocator.allocate(100)  # Allocates block with 28 bytes wasted
block2 = allocator.allocate(50)   # Allocates another block
print(f"Block1 index: {block1}, wasted: {128 - 100} bytes")
print(f"Block2 index: {block2}, wasted: {128 - 50} bytes")
Output
Block1 index: 0, wasted: 28 bytes Block2 index: 1, wasted: 78 bytes
↔️

External Fragmentation Equivalent

This example simulates variable-sized memory allocation that can cause external fragmentation.

python
class VariableSizeAllocator:
    def __init__(self, total_size):
        self.total_size = total_size
        self.free_blocks = [(0, total_size)]  # List of (start, size)
        self.allocated = {}

    def allocate(self, size):
        for i, (start, free_size) in enumerate(self.free_blocks):
            if free_size >= size:
                self.allocated[start] = size
                if free_size == size:
                    self.free_blocks.pop(i)
                else:
                    self.free_blocks[i] = (start + size, free_size - size)
                return start
        return -1  # No suitable block

    def free(self, start):
        if start in self.allocated:
            size = self.allocated.pop(start)
            self.free_blocks.append((start, size))
            self.free_blocks.sort()
            # Merge adjacent free blocks
            merged = []
            prev_start, prev_size = self.free_blocks[0]
            for curr_start, curr_size in self.free_blocks[1:]:
                if prev_start + prev_size == curr_start:
                    prev_size += curr_size
                else:
                    merged.append((prev_start, prev_size))
                    prev_start, prev_size = curr_start, curr_size
            merged.append((prev_start, prev_size))
            self.free_blocks = merged

allocator = VariableSizeAllocator(total_size=200)
addr1 = allocator.allocate(50)
addr2 = allocator.allocate(70)
allocator.free(addr1)
addr3 = allocator.allocate(60)  # Fails if no contiguous block >= 60
print(f"Allocated blocks at: {addr2} and {addr3}")
Output
Allocated blocks at: 50 and -1
🎯

When to Use Which

Choose internal fragmentation management (fixed-size blocks) when allocation speed and simplicity matter more than memory efficiency, such as in real-time systems or paging. It is easier to implement and faster but wastes some memory inside blocks.

Choose external fragmentation management (variable-sized allocation) when memory efficiency is critical and allocations vary widely in size, like in general-purpose operating systems. It requires more complex management and may need compaction but reduces wasted space outside blocks.

Key Takeaways

Internal fragmentation wastes memory inside fixed-size allocated blocks due to unused space.
External fragmentation wastes memory outside allocated blocks as scattered free spaces.
Internal fragmentation is simpler to manage but less memory efficient.
External fragmentation requires complex management like compaction to reduce wasted space.
Choose fixed-size allocation for speed and simplicity; choose variable-size for memory efficiency.