Home / Class/ BuddyChunk Class — netty Architecture

BuddyChunk Class — netty Architecture

Architecture documentation for the BuddyChunk class in AdaptivePoolingAllocator.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee["BuddyChunk"]
  fee3fa6d_a7fb_30d6_ea34_49602c633a2c["AdaptivePoolingAllocator.java"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|defined in| fee3fa6d_a7fb_30d6_ea34_49602c633a2c
  deffd968_35b6_23b3_53db_5f6b8278c6ce["BuddyChunk()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| deffd968_35b6_23b3_53db_5f6b8278c6ce
  a13d9512_d928_e5c6_faed_67181d87b829["readInitInto()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| a13d9512_d928_e5c6_faed_67181d87b829
  e96d016e_b4f4_6b32_d223_e56596e9b1f1["accept()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| e96d016e_b4f4_6b32_d223_e56596e9b1f1
  28e6d77f_4b9f_51aa_b832_9475c437bbcb["releaseSegment()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| 28e6d77f_4b9f_51aa_b832_9475c437bbcb
  f2e9fb63_e8bd_a2ee_114d_d7571fd4ad46["remainingCapacity()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| f2e9fb63_e8bd_a2ee_114d_d7571fd4ad46
  04f8cd58_f031_827b_41fb_b7445b790e37["hasUnprocessedFreelistEntries()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| 04f8cd58_f031_827b_41fb_b7445b790e37
  64a005fb_49a2_2033_49c6_cbcbad4ec48a["processFreelistEntries()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| 64a005fb_49a2_2033_49c6_cbcbad4ec48a
  09ad62f1_655a_04ec_8e0e_51a3c352654d["chooseFirstFreeBuddy()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| 09ad62f1_655a_04ec_8e0e_51a3c352654d
  dc83f7d4_74f8_e748_7e3b_3dcd31faa500["unreserveMatchingBuddy()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| dc83f7d4_74f8_e748_7e3b_3dcd31faa500
  ae0abbfc_6aa8_1b3b_c9f3_1219ef376071["String()"]
  fbf1f415_2f80_8493_e5fb_f8f9be5f99ee -->|method| ae0abbfc_6aa8_1b3b_c9f3_1219ef376071

Relationship Graph

Source Code

buffer/src/main/java/io/netty/buffer/AdaptivePoolingAllocator.java lines 1356–1534

    private static final class BuddyChunk extends Chunk implements IntConsumer {
        private static final int MIN_BUDDY_SIZE = 32768;
        private static final byte IS_CLAIMED = (byte) (1 << 7);
        private static final byte HAS_CLAIMED_CHILDREN = 1 << 6;
        private static final byte SHIFT_MASK = ~(IS_CLAIMED | HAS_CLAIMED_CHILDREN);
        private static final int PACK_OFFSET_MASK = 0xFFFF;
        private static final int PACK_SIZE_SHIFT = Integer.SIZE - Integer.numberOfLeadingZeros(PACK_OFFSET_MASK);

        private final MpscIntQueue freeList;
        // The bits of each buddy: [1: is claimed][1: has claimed children][30: MIN_BUDDY_SIZE shift to get size]
        private final byte[] buddies;
        private final int freeListCapacity;

        BuddyChunk(AbstractByteBuf delegate, Magazine magazine) {
            super(delegate, magazine, true);
            int capacity = delegate.capacity();
            int capFactor = capacity / MIN_BUDDY_SIZE;
            int tree = (capFactor << 1) - 1;
            int maxShift = Integer.numberOfTrailingZeros(capFactor);
            assert maxShift <= 30; // The top 2 bits are used for marking.
            freeListCapacity = tree >> 1;
            freeList = MpscIntQueue.create(freeListCapacity, -1); // At most half of tree (all leaf nodes) can be freed.
            buddies = new byte[1 + tree];

            // Generate the buddies entries.
            int index = 1;
            int runLength = 1;
            int currentRun = 0;
            while (maxShift > 0) {
                buddies[index++] = (byte) maxShift;
                if (++currentRun == runLength) {
                    currentRun = 0;
                    runLength <<= 1;
                    maxShift--;
                }
            }
        }

        @Override
        public boolean readInitInto(AdaptiveByteBuf buf, int size, int startingCapacity, int maxCapacity) {
            if (!freeList.isEmpty()) {
                freeList.drain(freeListCapacity, this);
            }
            int startIndex = chooseFirstFreeBuddy(1, startingCapacity, 0);
            if (startIndex == -1) {
                return false;
            }
            Chunk chunk = this;
            chunk.retain();
            try {
                buf.init(delegate, this, 0, 0, startIndex, size, startingCapacity, maxCapacity);
                allocatedBytes += startingCapacity;
                chunk = null;
            } finally {
                if (chunk != null) {
                    // If chunk is not null we know that buf.init(...) failed and so we need to manually release
                    // the chunk again as we retained it before calling buf.init(...).
                    chunk.release();
                }
            }
            return true;
        }

        @Override
        public void accept(int packed) {
            // Called by allocating thread when draining freeList.
            int size = MIN_BUDDY_SIZE << (packed >> PACK_SIZE_SHIFT);
            int offset = (packed & PACK_OFFSET_MASK) * MIN_BUDDY_SIZE;
            unreserveMatchingBuddy(1, size, offset, 0);
            allocatedBytes -= size;
        }

        @Override
        void releaseSegment(int startingIndex, int size) {
            int packedOffset = startingIndex / MIN_BUDDY_SIZE;
            int packedSize = Integer.numberOfTrailingZeros(size / MIN_BUDDY_SIZE) << PACK_SIZE_SHIFT;
            int packed = packedOffset | packedSize;
            freeList.offer(packed);
            release();
        }

Frequently Asked Questions

What is the BuddyChunk class?
BuddyChunk is a class in the netty codebase, defined in buffer/src/main/java/io/netty/buffer/AdaptivePoolingAllocator.java.
Where is BuddyChunk defined?
BuddyChunk is defined in buffer/src/main/java/io/netty/buffer/AdaptivePoolingAllocator.java at line 1356.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free