ref.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. #include "ref.h"
  2. #include "blob.h"
  3. #include <library/cpp/yt/malloc/malloc.h>
  4. #include <library/cpp/yt/misc/port.h>
  5. #include <util/system/info.h>
  6. #include <util/system/align.h>
  7. namespace NYT {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. namespace NDetail {
  10. // N.B. We would prefer these arrays to be zero sized
  11. // but zero sized arrays are not supported in MSVC.
  12. const char EmptyRefData[1] = {0};
  13. char MutableEmptyRefData[1] = {0};
  14. } // namespace NDetail
  15. ////////////////////////////////////////////////////////////////////////////////
  16. class TBlobHolder
  17. : public TSharedRangeHolder
  18. {
  19. public:
  20. explicit TBlobHolder(TBlob&& blob)
  21. : Blob_(std::move(blob))
  22. { }
  23. // TSharedRangeHolder overrides.
  24. std::optional<size_t> GetTotalByteSize() const override
  25. {
  26. return Blob_.Capacity();
  27. }
  28. private:
  29. const TBlob Blob_;
  30. };
  31. ////////////////////////////////////////////////////////////////////////////////
  32. class TStringHolder
  33. : public TSharedRangeHolder
  34. {
  35. public:
  36. TStringHolder(TString&& string, TRefCountedTypeCookie cookie)
  37. : String_(std::move(string))
  38. #ifdef YT_ENABLE_REF_COUNTED_TRACKING
  39. , Cookie_(cookie)
  40. #endif
  41. {
  42. #ifdef YT_ENABLE_REF_COUNTED_TRACKING
  43. TRefCountedTrackerFacade::AllocateTagInstance(Cookie_);
  44. TRefCountedTrackerFacade::AllocateSpace(Cookie_, String_.length());
  45. #endif
  46. }
  47. ~TStringHolder()
  48. {
  49. #ifdef YT_ENABLE_REF_COUNTED_TRACKING
  50. TRefCountedTrackerFacade::FreeTagInstance(Cookie_);
  51. TRefCountedTrackerFacade::FreeSpace(Cookie_, String_.length());
  52. #endif
  53. }
  54. const TString& String() const
  55. {
  56. return String_;
  57. }
  58. // TSharedRangeHolder overrides.
  59. std::optional<size_t> GetTotalByteSize() const override
  60. {
  61. return String_.capacity();
  62. }
  63. private:
  64. const TString String_;
  65. #ifdef YT_ENABLE_REF_COUNTED_TRACKING
  66. const TRefCountedTypeCookie Cookie_;
  67. #endif
  68. };
  69. ////////////////////////////////////////////////////////////////////////////////
  70. template <class TDerived>
  71. class TAllocationHolderBase
  72. : public TSharedRangeHolder
  73. {
  74. public:
  75. ~TAllocationHolderBase()
  76. {
  77. #ifdef YT_ENABLE_REF_COUNTED_TRACKING
  78. TRefCountedTrackerFacade::FreeTagInstance(Cookie_);
  79. TRefCountedTrackerFacade::FreeSpace(Cookie_, Size_);
  80. #endif
  81. }
  82. TMutableRef GetRef()
  83. {
  84. return TMutableRef(static_cast<TDerived*>(this)->GetBegin(), Size_);
  85. }
  86. protected:
  87. size_t Size_;
  88. #ifdef YT_ENABLE_REF_COUNTED_TRACKING
  89. TRefCountedTypeCookie Cookie_;
  90. #endif
  91. void Initialize(
  92. size_t size,
  93. TSharedMutableRefAllocateOptions options,
  94. TRefCountedTypeCookie cookie)
  95. {
  96. Size_ = size;
  97. Cookie_ = cookie;
  98. if (options.InitializeStorage) {
  99. ::memset(static_cast<TDerived*>(this)->GetBegin(), 0, Size_);
  100. }
  101. #ifdef YT_ENABLE_REF_COUNTED_TRACKING
  102. TRefCountedTrackerFacade::AllocateTagInstance(Cookie_);
  103. TRefCountedTrackerFacade::AllocateSpace(Cookie_, Size_);
  104. #endif
  105. }
  106. };
  107. ////////////////////////////////////////////////////////////////////////////////
  108. class TDefaultAllocationHolder
  109. : public TAllocationHolderBase<TDefaultAllocationHolder>
  110. , public TWithExtraSpace<TDefaultAllocationHolder>
  111. {
  112. public:
  113. TDefaultAllocationHolder(
  114. size_t size,
  115. TSharedMutableRefAllocateOptions options,
  116. TRefCountedTypeCookie cookie)
  117. {
  118. if (options.ExtendToUsableSize) {
  119. if (auto usableSize = GetUsableSpaceSize(); usableSize != 0) {
  120. size = usableSize;
  121. }
  122. }
  123. Initialize(size, options, cookie);
  124. }
  125. char* GetBegin()
  126. {
  127. return static_cast<char*>(GetExtraSpacePtr());
  128. }
  129. // TSharedRangeHolder overrides.
  130. std::optional<size_t> GetTotalByteSize() const override
  131. {
  132. return Size_;
  133. }
  134. };
  135. ////////////////////////////////////////////////////////////////////////////////
  136. class TPageAlignedAllocationHolder
  137. : public TAllocationHolderBase<TPageAlignedAllocationHolder>
  138. {
  139. public:
  140. TPageAlignedAllocationHolder(
  141. size_t size,
  142. TSharedMutableRefAllocateOptions options,
  143. TRefCountedTypeCookie cookie)
  144. : Begin_(static_cast<char*>(::aligned_malloc(size, GetPageSize())))
  145. {
  146. Initialize(size, options, cookie);
  147. }
  148. ~TPageAlignedAllocationHolder()
  149. {
  150. ::free(Begin_);
  151. }
  152. char* GetBegin()
  153. {
  154. return Begin_;
  155. }
  156. // TSharedRangeHolder overrides.
  157. std::optional<size_t> GetTotalByteSize() const override
  158. {
  159. return AlignUp(Size_, GetPageSize());
  160. }
  161. private:
  162. char* const Begin_;
  163. };
  164. ////////////////////////////////////////////////////////////////////////////////
  165. TRef TRef::FromBlob(const TBlob& blob)
  166. {
  167. return TRef(blob.Begin(), blob.Size());
  168. }
  169. bool TRef::AreBitwiseEqual(TRef lhs, TRef rhs)
  170. {
  171. if (lhs.Size() != rhs.Size()) {
  172. return false;
  173. }
  174. if (lhs.Size() == 0) {
  175. return true;
  176. }
  177. return ::memcmp(lhs.Begin(), rhs.Begin(), lhs.Size()) == 0;
  178. }
  179. ////////////////////////////////////////////////////////////////////////////////
  180. TMutableRef TMutableRef::FromBlob(TBlob& blob)
  181. {
  182. return TMutableRef(blob.Begin(), blob.Size());
  183. }
  184. ////////////////////////////////////////////////////////////////////////////////
  185. TSharedRef TSharedRef::FromString(TString str, TRefCountedTypeCookie tagCookie)
  186. {
  187. auto holder = New<TStringHolder>(std::move(str), tagCookie);
  188. auto ref = TRef::FromString(holder->String());
  189. return TSharedRef(ref, std::move(holder));
  190. }
  191. TSharedRef TSharedRef::FromBlob(TBlob&& blob)
  192. {
  193. auto ref = TRef::FromBlob(blob);
  194. auto holder = New<TBlobHolder>(std::move(blob));
  195. return TSharedRef(ref, std::move(holder));
  196. }
  197. TSharedRef TSharedRef::MakeCopy(TRef ref, TRefCountedTypeCookie tagCookie)
  198. {
  199. if (!ref) {
  200. return {};
  201. }
  202. if (ref.Empty()) {
  203. return TSharedRef::MakeEmpty();
  204. }
  205. auto result = TSharedMutableRef::Allocate(ref.Size(), {.InitializeStorage = false}, tagCookie);
  206. ::memcpy(result.Begin(), ref.Begin(), ref.Size());
  207. return result;
  208. }
  209. std::vector<TSharedRef> TSharedRef::Split(size_t partSize) const
  210. {
  211. YT_VERIFY(partSize > 0);
  212. std::vector<TSharedRef> result;
  213. result.reserve(Size() / partSize + 1);
  214. auto sliceBegin = Begin();
  215. while (sliceBegin < End()) {
  216. auto sliceEnd = sliceBegin + partSize;
  217. if (sliceEnd < sliceBegin || sliceEnd > End()) {
  218. sliceEnd = End();
  219. }
  220. result.push_back(Slice(sliceBegin, sliceEnd));
  221. sliceBegin = sliceEnd;
  222. }
  223. return result;
  224. }
  225. ////////////////////////////////////////////////////////////////////////////////
  226. TSharedMutableRef TSharedMutableRef::Allocate(size_t size, TSharedMutableRefAllocateOptions options, TRefCountedTypeCookie tagCookie)
  227. {
  228. auto holder = NewWithExtraSpace<TDefaultAllocationHolder>(size, size, options, tagCookie);
  229. auto ref = holder->GetRef();
  230. return TSharedMutableRef(ref, std::move(holder));
  231. }
  232. TSharedMutableRef TSharedMutableRef::AllocatePageAligned(size_t size, TSharedMutableRefAllocateOptions options, TRefCountedTypeCookie tagCookie)
  233. {
  234. auto holder = New<TPageAlignedAllocationHolder>(size, options, tagCookie);
  235. auto ref = holder->GetRef();
  236. return TSharedMutableRef(ref, std::move(holder));
  237. }
  238. TSharedMutableRef TSharedMutableRef::FromBlob(TBlob&& blob)
  239. {
  240. auto ref = TMutableRef::FromBlob(blob);
  241. auto holder = New<TBlobHolder>(std::move(blob));
  242. return TSharedMutableRef(ref, std::move(holder));
  243. }
  244. TSharedMutableRef TSharedMutableRef::MakeCopy(TRef ref, TRefCountedTypeCookie tagCookie)
  245. {
  246. if (!ref) {
  247. return {};
  248. }
  249. if (ref.Empty()) {
  250. return TSharedMutableRef::MakeEmpty();
  251. }
  252. auto result = Allocate(ref.Size(), {.InitializeStorage = false}, tagCookie);
  253. ::memcpy(result.Begin(), ref.Begin(), ref.Size());
  254. return result;
  255. }
  256. ////////////////////////////////////////////////////////////////////////////////
  257. TString ToString(TRef ref)
  258. {
  259. return TString(ref.Begin(), ref.End());
  260. }
  261. TString ToString(const TMutableRef& ref)
  262. {
  263. return ToString(TRef(ref));
  264. }
  265. TString ToString(const TSharedRef& ref)
  266. {
  267. return ToString(TRef(ref));
  268. }
  269. TString ToString(const TSharedMutableRef& ref)
  270. {
  271. return ToString(TRef(ref));
  272. }
  273. size_t GetPageSize()
  274. {
  275. static const size_t PageSize = NSystemInfo::GetPageSize();
  276. return PageSize;
  277. }
  278. size_t RoundUpToPage(size_t bytes)
  279. {
  280. return AlignUp<size_t>(bytes, GetPageSize());
  281. }
  282. size_t GetByteSize(const TSharedRefArray& array)
  283. {
  284. size_t size = 0;
  285. if (array) {
  286. for (const auto& part : array) {
  287. size += part.Size();
  288. }
  289. }
  290. return size;
  291. }
  292. ////////////////////////////////////////////////////////////////////////////////
  293. i64 TSharedRefArray::ByteSize() const
  294. {
  295. i64 result = 0;
  296. if (*this) {
  297. for (const auto& part : *this) {
  298. result += part.Size();
  299. }
  300. }
  301. return result;
  302. }
  303. std::vector<TSharedRef> TSharedRefArray::ToVector() const
  304. {
  305. if (!Impl_) {
  306. return {};
  307. }
  308. return std::vector<TSharedRef>(Begin(), End());
  309. }
  310. TString TSharedRefArray::ToString() const
  311. {
  312. if (!Impl_) {
  313. return {};
  314. }
  315. TString result;
  316. size_t size = 0;
  317. for (const auto& part : *this) {
  318. size += part.size();
  319. }
  320. result.ReserveAndResize(size);
  321. char* ptr = result.begin();
  322. for (const auto& part : *this) {
  323. size += part.size();
  324. ::memcpy(ptr, part.begin(), part.size());
  325. ptr += part.size();
  326. }
  327. return result;
  328. }
  329. TSharedRefArray TSharedRefArray::MakeCopy(
  330. const TSharedRefArray& array,
  331. TRefCountedTypeCookie tagCookie)
  332. {
  333. TSharedRefArrayBuilder builder(
  334. array.Size(),
  335. array.ByteSize(),
  336. tagCookie);
  337. for (const auto& part : array) {
  338. auto partCopy = builder.AllocateAndAdd(part.Size());
  339. ::memcpy(partCopy.Begin(), part.Begin(), part.Size());
  340. }
  341. return builder.Finish();
  342. }
  343. ////////////////////////////////////////////////////////////////////////////////
  344. TSharedRefArrayBuilder::TSharedRefArrayBuilder(
  345. size_t size,
  346. size_t poolCapacity,
  347. TRefCountedTypeCookie tagCookie)
  348. : AllocationCapacity_(poolCapacity)
  349. , Impl_(TSharedRefArray::NewImpl(
  350. size,
  351. poolCapacity,
  352. tagCookie,
  353. size))
  354. , CurrentAllocationPtr_(Impl_->GetBeginAllocationPtr())
  355. { }
  356. void TSharedRefArrayBuilder::Add(TSharedRef part)
  357. {
  358. YT_ASSERT(CurrentPartIndex_ < Impl_->Size());
  359. Impl_->MutableBegin()[CurrentPartIndex_++] = std::move(part);
  360. }
  361. TMutableRef TSharedRefArrayBuilder::AllocateAndAdd(size_t size)
  362. {
  363. YT_ASSERT(CurrentPartIndex_ < Impl_->Size());
  364. YT_ASSERT(CurrentAllocationPtr_ + size <= Impl_->GetBeginAllocationPtr() + AllocationCapacity_);
  365. TMutableRef ref(CurrentAllocationPtr_, size);
  366. CurrentAllocationPtr_ += size;
  367. TSharedRangeHolderPtr holder(Impl_.Get(), false);
  368. TSharedRef sharedRef(ref, std::move(holder));
  369. Add(std::move(sharedRef));
  370. return ref;
  371. }
  372. TSharedRefArray TSharedRefArrayBuilder::Finish()
  373. {
  374. return TSharedRefArray(std::move(Impl_));
  375. }
  376. ////////////////////////////////////////////////////////////////////////////////
  377. } // namespace NYT