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();
}
Source
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