chunked_memory_pool.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #pragma once
  2. #include "public.h"
  3. #include "ref.h"
  4. #include <library/cpp/yt/misc/port.h>
  5. #include <util/generic/size_literals.h>
  6. namespace NYT {
  7. ////////////////////////////////////////////////////////////////////////////////
  8. struct TDefaultChunkedMemoryPoolTag { };
  9. // TAllocationHolder is polymorphic. So we cannot use TWithExtraSpace mixin
  10. // because it needs the most derived type as a template argument and
  11. // it would require GetExtraSpacePtr/GetRef methods to be virtual.
  12. class TAllocationHolder
  13. {
  14. public:
  15. TAllocationHolder(TMutableRef ref, TRefCountedTypeCookie cookie);
  16. TAllocationHolder(const TAllocationHolder&) = delete;
  17. TAllocationHolder(TAllocationHolder&&) = default;
  18. virtual ~TAllocationHolder();
  19. void operator delete(void* ptr) noexcept;
  20. TMutableRef GetRef() const;
  21. template <class TDerived>
  22. static TDerived* Allocate(size_t size, TRefCountedTypeCookie cookie);
  23. private:
  24. const TMutableRef Ref_;
  25. #ifdef YT_ENABLE_REF_COUNTED_TRACKING
  26. const TRefCountedTypeCookie Cookie_;
  27. #endif
  28. };
  29. ////////////////////////////////////////////////////////////////////////////////
  30. struct IMemoryChunkProvider
  31. : public TRefCounted
  32. {
  33. virtual std::unique_ptr<TAllocationHolder> Allocate(size_t size, TRefCountedTypeCookie cookie) = 0;
  34. };
  35. DEFINE_REFCOUNTED_TYPE(IMemoryChunkProvider)
  36. const IMemoryChunkProviderPtr& GetDefaultMemoryChunkProvider();
  37. ////////////////////////////////////////////////////////////////////////////////
  38. class TChunkedMemoryPool
  39. : private TNonCopyable
  40. {
  41. public:
  42. static constexpr size_t DefaultStartChunkSize = 4_KB;
  43. static constexpr size_t RegularChunkSize = 36_KB - 512;
  44. TChunkedMemoryPool(
  45. TRefCountedTypeCookie tagCookie,
  46. IMemoryChunkProviderPtr chunkProvider,
  47. size_t startChunkSize = DefaultStartChunkSize);
  48. explicit TChunkedMemoryPool(
  49. TRefCountedTypeCookie tagCookie,
  50. size_t startChunkSize = DefaultStartChunkSize);
  51. TChunkedMemoryPool();
  52. template <class TTag>
  53. explicit TChunkedMemoryPool(
  54. TTag,
  55. size_t startChunkSize = DefaultStartChunkSize);
  56. //! Allocates #sizes bytes without any alignment.
  57. char* AllocateUnaligned(size_t size);
  58. //! Allocates #size bytes aligned with 8-byte granularity.
  59. char* AllocateAligned(size_t size, int align = 8);
  60. //! Allocates #n uninitialized instances of #T.
  61. template <class T>
  62. T* AllocateUninitialized(int n, int align = alignof(T));
  63. //! Allocates space and copies #src inside it.
  64. template <class T>
  65. TMutableRange<T> Capture(TRange<T> src, int align = alignof(T));
  66. //! Frees memory range if possible: namely, if the free region is a suffix of last allocated region.
  67. void Free(char* from, char* to);
  68. //! Marks all previously allocated small chunks as free for subsequent allocations but
  69. //! does not deallocate them.
  70. //! Purges all large blocks.
  71. void Clear();
  72. //! Purges all allocated memory, including small chunks.
  73. void Purge();
  74. //! Returns the number of allocated bytes.
  75. size_t GetSize() const;
  76. //! Returns the number of reserved bytes.
  77. size_t GetCapacity() const;
  78. //! Returns the number of bytes that can be acquired in the current chunk
  79. //! without additional allocations.
  80. size_t GetCurrentChunkSpareSize() const;
  81. //! Moves all the allocated memory from other memory pool to the current one.
  82. //! The other pool becomes empty, like after Purge() call.
  83. void Absorb(TChunkedMemoryPool&& other);
  84. private:
  85. const TRefCountedTypeCookie TagCookie_;
  86. // A common use case is to construct TChunkedMemoryPool with the default
  87. // memory chunk provider. The latter is ref-counted and is shared between
  88. // a multitude of TChunkedMemoryPool instances. This could potentially
  89. // lead to a contention over IMemoryChunkProvider's ref-counter.
  90. // To circumvent this, we keep both an owning (#ChunkProviderHolder_) and
  91. // a non-owning (#ChunkProvider_) reference to the underlying provider.
  92. // In case of the default chunk provider, the owning reference is not used.
  93. const IMemoryChunkProviderPtr ChunkProviderHolder_;
  94. IMemoryChunkProvider* const ChunkProvider_;
  95. int NextChunkIndex_ = 0;
  96. size_t NextSmallSize_;
  97. size_t Size_ = 0;
  98. size_t Capacity_ = 0;
  99. // Chunk memory layout:
  100. // |AAAA|....|UUUU|
  101. // Legend:
  102. // A aligned allocations
  103. // U unaligned allocations
  104. // . free zone
  105. char* FreeZoneBegin_;
  106. char* FreeZoneEnd_;
  107. std::vector<std::unique_ptr<TAllocationHolder>> Chunks_;
  108. std::vector<std::unique_ptr<TAllocationHolder>> OtherBlocks_;
  109. void Initialize(size_t startChunkSize);
  110. char* AllocateUnalignedSlow(size_t size);
  111. char* AllocateAlignedSlow(size_t size, int align);
  112. char* AllocateSlowCore(size_t size);
  113. };
  114. ////////////////////////////////////////////////////////////////////////////////
  115. } // namespace NYT
  116. #define CHUNKED_MEMORY_POOL_INL_H_
  117. #include "chunked_memory_pool-inl.h"
  118. #undef CHUNKED_MEMORY_POOL_INL_H_