ref.cpp 12 KB

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