| 50 | } |
| 51 | |
| 52 | void ArenaPlanner::commit() |
| 53 | { |
| 54 | if (!dirty) |
| 55 | return; |
| 56 | |
| 57 | // Determine the chunks to allocate. Each chunk contains one or more allocations consecutively |
| 58 | struct Chunk |
| 59 | { |
| 60 | Alloc* firstAlloc; |
| 61 | int firstOpID; |
| 62 | int lastOpID; |
| 63 | size_t byteSize; |
| 64 | size_t byteAlignment; |
| 65 | }; |
| 66 | |
| 67 | std::vector<Chunk> chunks; |
| 68 | |
| 69 | // Iterate over all allocations and find the first allocation in each chunk |
| 70 | for (const auto& alloc : allocs) |
| 71 | { |
| 72 | // If the allocation is not the first in a chunk, skip it |
| 73 | if (alloc->prev) |
| 74 | continue; |
| 75 | |
| 76 | // Initialize the chunk |
| 77 | Chunk chunk; |
| 78 | chunk.firstAlloc = alloc.get(); |
| 79 | chunk.byteSize = 0; |
| 80 | chunk.byteAlignment = alloc->byteAlignment; |
| 81 | chunk.firstOpID = alloc->firstOpID; |
| 82 | chunk.lastOpID = alloc->lastOpID; |
| 83 | |
| 84 | // Iterate over all allocations in the chunk |
| 85 | for (Alloc* curAlloc = chunk.firstAlloc; curAlloc; curAlloc = curAlloc->next) |
| 86 | { |
| 87 | chunk.byteSize += curAlloc->byteSize; |
| 88 | chunk.firstOpID = min(chunk.firstOpID, curAlloc->firstOpID); |
| 89 | chunk.lastOpID = max(chunk.lastOpID, curAlloc->lastOpID); |
| 90 | } |
| 91 | |
| 92 | chunks.push_back(chunk); |
| 93 | } |
| 94 | |
| 95 | // Sort the chunks by size in descending order |
| 96 | std::sort(chunks.begin(), chunks.end(), |
| 97 | [](const Chunk& a, const Chunk& b) { return a.byteSize > b.byteSize; }); |
| 98 | |
| 99 | // Track the active allocations sorted by offset in ascending order |
| 100 | std::vector<Alloc*> activeAllocs; |
| 101 | totalByteSize = 0; |
| 102 | |
| 103 | // Iterate over the sorted chunks to allocate |
| 104 | for (const Chunk& chunk : chunks) |
| 105 | { |
| 106 | size_t curByteOffset = 0; |
| 107 | size_t bestByteOffset = SIZE_MAX; |
| 108 | size_t bestGapByteSize = SIZE_MAX; |
| 109 | |