[PATCH] D133713: [Support] Introduce ThreadSafeAllocator
Steven Wu via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 6 09:16:35 PST 2023
steven_wu added a comment.
@dexonsmith Move the discussion here.
> Here's a sketch that I think mostly works?
>
> // Block for bump allocations.
> struct BumpBlock {
> std::atomic<char *> Ptr;
> std::atomic<BumpBlock *> Next;
> char Bytes[4084];
> BumpBlock() : Ptr{Bytes}, Next{nullptr} {}
>
> // Compute new "Next", try to bump if there's space, else return nullptr.
> void *tryAllocate(size_t N, size_t Align = 1);
> };
>
> // Tail-allocated data for "big" allocations.
> struct BumpSeparate {
> std::atomic<BumpSeparate *> Next;
> // tail-allocated data of appropriate and alignment, using malloc....
> };
>
> // Allocator.
> struct BumpAllocator {
> std::atomic<BumpBlock *> CurrentBlock;
> std::atomic<BumpSeparate *> LastAllocSeparately;
>
> // Delete everything since there's no ownership here...
> ~BumpAllocator();
>
> void *allocate(size_t N, size_t Align = 1) {
> if (N > 2048)
> return allocateSeparately(N, Align);
>
> BumpBlock *B = CurrentBlock;
> std::unique_ptr<BumpBlock> New;
> void *NewAlloc = nullptr;
> while (true) {
> if (LLVM_LIKELY(B))
> if (void *Alloc = B->tryAllocate(N, Align))
> return Alloc;
>
> if (!New) {
> New = new BumpBlock;
> NewAlloc = New->tryAllocate(N, Align);
> assert(NewAlloc && "Empty block doesn't have space!");
> }
> if (!CurrentBlock.compare_exchange_weak(B, New.get()))
> continue;
>
> // New was saved in CurrentBlock. Fix its "Next" pointer and release it
> // so it's not deallocated.
> New->Next = B;
> New.release();
> return NewAlloc;
> }
> }
>
> private:
> // Maintain a list of "big" allocations, similar to above.
> void *allocateSeparately(size_t N, size_t Align);
> };
>
> Not saying it needs to block this review...
>
> But having a fast concurrent BumpPtrAllocator would be independently useful, and I'd suggest optimizing the allocator before bloating the default trie size.
>
> Yes, the FIXME for a ThreadSafeBumpPtrAllocator is still there. Currently, I don't think it is urgent to fix. It is not expected to have someone to use Trie as a high performance thread safe set/map.
> The immediate use case is as a high performance thread-safe data store. In the CAS use case we're expecting a lot of duplicate insertions which don't happen to hit the allocator, but I'm not sure that's really been checked/measured.
The algorithm works. Your sketch can have a small allocation in a slab when a conflict happens but that should be easy to fix.
The reason I don't want to have the CAS blocked by a better allocator is that I need to write and test it, also figure out if it needs to have any code sharing with regular BumpPtrAllocator.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D133713/new/
https://reviews.llvm.org/D133713
More information about the llvm-commits
mailing list