diff options
author | innokentii <innokentii@yandex-team.com> | 2022-11-08 10:19:21 +0300 |
---|---|---|
committer | innokentii <innokentii@yandex-team.com> | 2022-11-08 10:19:21 +0300 |
commit | b23296965af8123d5f9a4f6b7ad38e993b7b0575 (patch) | |
tree | f448d1368ce234d2ce80a9414c8857ad589ad318 | |
parent | bed275eb55181fa9a445a6af7d54bd49c278e5cb (diff) | |
download | ydb-b23296965af8123d5f9a4f6b7ad38e993b7b0575.tar.gz |
Add owner-based shared_data backend impl for contiguous_data
add owner-based shared_data backend impl for contiguous_data
-rw-r--r-- | library/cpp/actors/util/CMakeLists.txt | 1 | ||||
-rw-r--r-- | library/cpp/actors/util/contiguous_data.cpp | 50 | ||||
-rw-r--r-- | library/cpp/actors/util/contiguous_data.h | 289 | ||||
-rw-r--r-- | library/cpp/actors/util/contiguous_data_ut.cpp | 48 | ||||
-rw-r--r-- | library/cpp/actors/util/shared_data_backtracing_owner.h | 8 |
5 files changed, 213 insertions, 183 deletions
diff --git a/library/cpp/actors/util/CMakeLists.txt b/library/cpp/actors/util/CMakeLists.txt index 19f683cb2a..96eee91c9e 100644 --- a/library/cpp/actors/util/CMakeLists.txt +++ b/library/cpp/actors/util/CMakeLists.txt @@ -18,6 +18,7 @@ target_sources(cpp-actors-util PRIVATE ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/affinity.cpp ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_track.cpp ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/memory_tracker.cpp + ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/contiguous_data.cpp ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/shared_data.cpp ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/should_continue.cpp ${CMAKE_SOURCE_DIR}/library/cpp/actors/util/threadparkpad.cpp diff --git a/library/cpp/actors/util/contiguous_data.cpp b/library/cpp/actors/util/contiguous_data.cpp new file mode 100644 index 0000000000..8a9cb6ef1a --- /dev/null +++ b/library/cpp/actors/util/contiguous_data.cpp @@ -0,0 +1,50 @@ +#include "contiguous_data.h" + +size_t checkedSum(size_t a, size_t b) { + if (a > std::numeric_limits<size_t>::max() - b) { + throw std::length_error("Allocate size overflow"); + } + return a + b; +} + +char* TContiguousData::TBackend::TSharedDataControllingOwner::Allocate(size_t size, size_t headroom, size_t tailroom) { + char* data = nullptr; + + size_t fullSize = checkedSum(size, checkedSum(headroom, tailroom)); + + if (fullSize > 0) { + auto allocSize = checkedSum(fullSize, OverheadSize); + char* raw = static_cast<char*>(y_allocate(allocSize)); + + auto isAligned = [](const void * ptr, std::uintptr_t alignment) noexcept { + auto iptr = reinterpret_cast<std::uintptr_t>(ptr); + return !(iptr % alignment); + }; + Y_VERIFY(isAligned(raw, alignof(TBackend::TCookies))); + TBackend::TCookies* cookies = new(raw) TBackend::TCookies(); + + auto* header = reinterpret_cast<NActors::TSharedData::THeader*>(raw + PrivateHeaderSize); + header->RefCount = 1; + header->Owner = &TContiguousData::TBackend::SharedDataOwner; + + data = raw + OverheadSize; + cookies->Begin = data + headroom; + cookies->End = data + headroom + size; + } + return data; +} + +bool TContiguousData::TBackend::TSharedDataControllingOwner::CheckControlled(const char *data) noexcept { + if (data != nullptr) { + auto* header = reinterpret_cast<const NActors::TSharedData::THeader*>(data - HeaderSize); +#ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW + // WARNING: with this definition method should be called ONLY on instances + // which passed through TBackTracingOwner::FakeOwner + const TBackTracingOwner* owner = reinterpret_cast<const TBackTracingOwner*>(header->Owner); + return owner->GetRealOwner() == &TContiguousData::TBackend::SharedDataOwner; +#else + return header->Owner == &TContiguousData::TBackend::SharedDataOwner; +#endif + } + return false; +} diff --git a/library/cpp/actors/util/contiguous_data.h b/library/cpp/actors/util/contiguous_data.h index e161a511c2..c52ef4b7d8 100644 --- a/library/cpp/actors/util/contiguous_data.h +++ b/library/cpp/actors/util/contiguous_data.h @@ -11,6 +11,7 @@ #include <util/system/sanitizers.h> #include <util/system/valgrind.h> #include <util/generic/array_ref.h> +#include <util/system/sys_alloc.h> #include "shared_data.h" @@ -294,7 +295,7 @@ class TContiguousData { enum class EType : uintptr_t { STRING, SHARED_DATA, - SHARED_DATA_CONTROLLED, + SHARED_DATA_CONTROLLED_BY_OWNER, ROPE_CHUNK_BACKEND, }; @@ -329,6 +330,44 @@ class TContiguousData { return size + BytesToAligned(size) + sizeof(TSelf); } }; + + struct TSharedDataControllingOwner : public NActors::TSharedData::IOwner { + enum : size_t { + PrivateHeaderSize = sizeof(TCookies), + HeaderSize = sizeof(NActors::TSharedData::THeader), + OverheadSize = PrivateHeaderSize + HeaderSize, + MaxDataSize = (std::numeric_limits<size_t>::max() - OverheadSize) + }; + + static char* Allocate(size_t size, size_t headroom = 0, size_t tailroom = 0); + + static TCookies* GetCookies(char* data) noexcept { + if (data != nullptr) { + return reinterpret_cast<TCookies*>(data - OverheadSize); + } + return nullptr; + } + + static const TCookies* GetCookies(const char* data) noexcept { + if (data != nullptr) { + return reinterpret_cast<const TCookies*>(data - OverheadSize); + } + return nullptr; + } + + static bool CheckControlled(const char* data) noexcept; + + void Deallocate(char* data) noexcept override { + if (data) { + char* raw = data - OverheadSize; + TCookies* cookies = reinterpret_cast<TCookies*>(raw); + cookies->~TCookies(); + y_deallocate(raw); + } + } + }; + + inline static TSharedDataControllingOwner SharedDataOwner {}; static constexpr struct TControlToken {} ControlToken; static constexpr size_t CookiesSize = sizeof(TCookies); @@ -346,12 +385,9 @@ class TContiguousData { : Owner(Construct<TString>(EType::STRING, std::move(s))) {} - TBackend(NActors::TSharedData s, TControlToken) - : Owner(Construct<NActors::TSharedData>(EType::SHARED_DATA_CONTROLLED, std::move(s))) - {} - TBackend(NActors::TSharedData s) - : Owner(Construct<NActors::TSharedData>(EType::SHARED_DATA, std::move(s))) + : Owner(Construct<NActors::TSharedData>( + TSharedDataControllingOwner::CheckControlled(s.data()) ? EType::SHARED_DATA_CONTROLLED_BY_OWNER : EType::SHARED_DATA, std::move(s))) {} TBackend(IContiguousChunk::TPtr backend) @@ -400,20 +436,52 @@ class TContiguousData { return reinterpret_cast<const void*>(Owner.Data[0]); } + TCookies* GetCookies() { + if(!Owner) { + return nullptr; + } + return Visit(Owner, [](EType type, auto& value) -> TCookies* { + using T = std::decay_t<decltype(value)>; + if constexpr (std::is_same_v<T, NActors::TSharedData>) { + if (type == EType::SHARED_DATA_CONTROLLED_BY_OWNER) { + return TSharedDataControllingOwner::GetCookies(const_cast<char*>(value.data())); + } else { + return nullptr; + } + } else { + return nullptr; + } + }); + } + + const TCookies* GetCookies() const { + return const_cast<TBackend&>(*this).GetCookies(); + } + + bool IsPrivate() const { + if(!Owner) { + return true; + } + return Visit(Owner, [](EType, auto& value) -> bool { + using T = std::decay_t<decltype(value)>; + if constexpr (std::is_same_v<T, NActors::TSharedData>) { + return value.IsPrivate(); + } else { + return false; + } + }); + } + TContiguousSpan GetData() const { if (!Owner) { return TContiguousSpan(); } - return Visit(Owner, [](EType type, auto& value) -> TContiguousSpan { + return Visit(Owner, [](EType, auto& value) -> TContiguousSpan { using T = std::decay_t<decltype(value)>; if constexpr (std::is_same_v<T, TString>) { return {&(*value.cbegin()), value.size()}; } else if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - return {value.data(), value.size() - CookiesSize}; - } else { - return {value.data(), value.size()}; - } + return {value.data(), value.size()}; } else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) { return value->GetData(); } else { @@ -426,7 +494,7 @@ class TContiguousData { if (!Owner) { return TMutableContiguousSpan(); } - return Visit(Owner, [](EType type, auto& value) -> TMutableContiguousSpan { + return Visit(Owner, [](EType, auto& value) -> TMutableContiguousSpan { using T = std::decay_t<decltype(value)>; if constexpr (std::is_same_v<T, TString>) { return {value.Detach(), value.size()}; @@ -434,11 +502,7 @@ class TContiguousData { if (value.IsShared()) { value = NActors::TSharedData::Copy(value.data(), value.size()); } - if (type == EType::SHARED_DATA_CONTROLLED) { - return {value.mutable_data(), value.size() - CookiesSize}; - } else { - return {value.mutable_data(), value.size()}; - } + return {value.mutable_data(), value.size()}; } else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) { return value->GetDataMut(); } else { @@ -451,16 +515,12 @@ class TContiguousData { if (!Owner) { return TMutableContiguousSpan(); } - return Visit(Owner, [](EType type, auto& value) -> TMutableContiguousSpan { + return Visit(Owner, [](EType, auto& value) -> TMutableContiguousSpan { using T = std::decay_t<decltype(value)>; if constexpr (std::is_same_v<T, TString>) { return {const_cast<char*>(value.data()), value.size()}; } else if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - return {const_cast<char*>(value.data()), value.size() - CookiesSize}; - } else { - return {const_cast<char*>(value.data()), value.size()}; - } + return {const_cast<char*>(value.data()), value.size()}; } else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) { return value->UnsafeGetDataMut(); } else { @@ -502,127 +562,59 @@ class TContiguousData { if (!Owner) { return false; } - return Visit(Owner, [contBegin = begin](EType type, auto& value) { - using T = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - auto* begin = value.data() + value.size() - CookiesSize; - const TCookies* cookies = reinterpret_cast<const TCookies*>(begin); - return value.IsPrivate() || cookies->Begin.load() == contBegin; - } - } - return false; - }); + const TCookies* cookies = GetCookies(); + return cookies && (IsPrivate() || cookies->Begin.load() == begin); } bool CanGrowBack(const char* end) const { if (!Owner) { return false; } - return Visit(Owner, [contEnd = end](EType type, auto& value) { - using T = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - auto* begin = value.data() + value.size() - CookiesSize; - const TCookies* cookies = reinterpret_cast<const TCookies*>(begin); - return value.IsPrivate() || cookies->End.load() == contEnd; - } - } - return false; - }); + const TCookies* cookies = GetCookies(); + return cookies && (IsPrivate() || cookies->End.load() == end); } void UpdateCookiesUnsafe(const char* contBegin, const char* contEnd) { if (!Owner) { return; } - return Visit(Owner, [contBegin, contEnd](EType type, auto& value) { - using T = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - auto* begin = const_cast<char*>(value.data() + value.size() - CookiesSize); - TCookies* cookies = reinterpret_cast<TCookies*>(begin); - cookies->Begin.store(contBegin); - cookies->End.store(contEnd); - } - } - }); - } - - bool UpdateCookies(const char* curBegin, const char* contBegin, const char* curEnd, const char* contEnd) { - if (!Owner) { - return false; + TCookies* cookies = GetCookies(); + if (cookies) { + cookies->Begin.store(contBegin); + cookies->End.store(contEnd); } - return Visit(Owner, [curBegin, contBegin, curEnd, contEnd](EType type, auto& value) mutable { - using T = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - auto* begin = const_cast<char*>(value.data() + value.size() - CookiesSize); - TCookies* cookies = reinterpret_cast<TCookies*>(begin); - if(cookies->Begin.compare_exchange_weak(curBegin, contBegin)) { - if(!cookies->End.compare_exchange_weak(curEnd, contEnd)) { - cookies->Begin.store(curBegin); // rollback - return false; - } - return true; - } - } - return false; - } - - return false; - }); } bool UpdateCookiesBegin(const char* curBegin, const char* contBegin) { if (!Owner) { return false; } - return Visit(Owner, [curBegin, contBegin](EType type, auto& value) mutable { - using T = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - auto* begin = const_cast<char*>(value.data() + value.size() - CookiesSize); - TCookies* cookies = reinterpret_cast<TCookies*>(begin); - return cookies->Begin.compare_exchange_weak(curBegin, contBegin); - } - } - return false; - }); + + TCookies* cookies = GetCookies(); + if (cookies) { + return cookies->Begin.compare_exchange_weak(curBegin, contBegin); + } + return false; } bool UpdateCookiesEnd(const char* curEnd, const char* contEnd) { if (!Owner) { return false; } - return Visit(Owner, [curEnd, contEnd](EType type, auto& value) mutable { - using T = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - auto* begin = const_cast<char*>(value.data() + value.size() - CookiesSize); - TCookies* cookies = reinterpret_cast<TCookies*>(begin); - return cookies->End.compare_exchange_weak(curEnd, contEnd); - } - } - return false; - }); + + TCookies* cookies = GetCookies(); + if (cookies) { + return cookies->End.compare_exchange_weak(curEnd, contEnd); + } + return false; } void Disown() { if (Owner) { const EType type = static_cast<EType>(Owner.Data[0] & TypeMask); - if (type == EType::SHARED_DATA_CONTROLLED) { - bool isPrivate = Visit(Owner, [](EType type, auto& value) { - using T = std::decay_t<decltype(value)>; - if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - return value.IsPrivate(); - } - } - return false; - }); - if (!isPrivate) { + if (type == EType::SHARED_DATA_CONTROLLED_BY_OWNER) { + if (IsPrivate()) { Owner.Data[0] = (Owner.Data[0] & ValueMask) | static_cast<uintptr_t>(EType::SHARED_DATA); } } @@ -634,16 +626,9 @@ class TContiguousData { if (!Owner) { return TResult{}; } - return Visit(Owner, [](EType type, auto& value) { + return Visit(Owner, [](EType, auto& value) { using T = std::decay_t<decltype(value)>; if constexpr (std::is_same_v<T, TResult>) { - if constexpr (std::is_same_v<T, NActors::TSharedData>) { - if (type == EType::SHARED_DATA_CONTROLLED) { - NActors::TSharedData data = value; - data.Trim(data.size() - CookiesSize); - return data; - } - } return value; } else { Y_FAIL(); @@ -682,15 +667,15 @@ class TContiguousData { }; template<typename TObject> - static TBackendHolder Construct(EType type, TObject object) { + static TBackendHolder Construct(EType type, TObject&& object) { if constexpr (sizeof(TObject) <= sizeof(TBackendHolder)) { TBackendHolder res = TBackend::Empty; - new(&res) TObject(std::move(object)); + new(&res) std::decay_t<TObject>(std::forward<TObject>(object)); Y_VERIFY_DEBUG((res.Data[0] & ValueMask) == res.Data[0]); res.Data[0] = res.Data[0] | static_cast<uintptr_t>(type); return res; } else { - return Construct<TObjectHolder<TObject>>(type, TObjectHolder<TObject>(std::move(object))); + return Construct<TObjectHolder<TObject>>(type, TObjectHolder<TObject>(std::forward<TObject>(object))); } } @@ -721,10 +706,10 @@ class TContiguousData { } }; switch (type) { - case EType::STRING: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const TString&, TString&>>(value)); - case EType::SHARED_DATA_CONTROLLED: [[fallthrough]]; - case EType::SHARED_DATA: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const NActors::TSharedData&, NActors::TSharedData&>>(value)); - case EType::ROPE_CHUNK_BACKEND: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const IContiguousChunk::TPtr&, IContiguousChunk::TPtr&>>(value)); + case EType::STRING: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const TString&, TString&>>(value)); + case EType::SHARED_DATA_CONTROLLED_BY_OWNER: [[fallthrough]]; + case EType::SHARED_DATA: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const NActors::TSharedData&, NActors::TSharedData&>>(value)); + case EType::ROPE_CHUNK_BACKEND: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const IContiguousChunk::TPtr&, IContiguousChunk::TPtr&>>(value)); } Y_FAIL("Unexpected type# %" PRIu64, static_cast<ui64>(type)); } @@ -762,14 +747,15 @@ class TContiguousData { const char *Begin; // data start const char *End; // data end - explicit TContiguousData(NActors::TSharedData s, TBackend::TCookies* cookies, TBackend::TControlToken) - : Backend(std::move(s), TBackend::ControlToken) + explicit TContiguousData(NActors::TSharedData s, const char *data, size_t size, TBackend::TControlToken) + : Backend(std::move(s)) { - auto span = Backend.GetData(); - Begin = span.data(); - End = Begin + span.size(); - cookies->Begin.store(Begin); - cookies->End.store(End); + Y_VERIFY(s.data() == nullptr || TBackend::TSharedDataControllingOwner::CheckControlled(s.data())); + Y_VERIFY(s.data() == nullptr || + (TBackend::TSharedDataControllingOwner::GetCookies(s.data())->Begin == data + && TBackend::TSharedDataControllingOwner::GetCookies(s.data())->End == data + size)); + Begin = data; + End = data + size; } TContiguousData(TOwnedSlice, const char *data, size_t size, const TContiguousData& from) @@ -850,7 +836,6 @@ public: Y_VERIFY(data >= from.GetData()); Y_VERIFY(data < from.GetData() + from.GetSize()); Y_VERIFY(data + size <= from.GetData() + from.GetSize()); - Backend.Disown(); } TContiguousData(TSlice, const char *begin, const char *end, const TContiguousData& from) @@ -878,10 +863,9 @@ public: return TContiguousData(); } if (headroom == 0 && tailroom == 0) { + NActors::TSharedData res = NActors::TSharedData::AttachUnsafe(TBackend::TSharedDataControllingOwner::Allocate(size), size); #ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW - NActors::TSharedData res = TBackTracingOwner::Allocate(size, TBackTracingOwner::INFO_ALLOC_UNINITIALIZED); -#else - NActors::TSharedData res = NActors::TSharedData::Uninitialized(size); + TBackTracingOwner::FakeOwner(res, TBackTracingOwner::INFO_ALLOC_UNINITIALIZED); #endif return TContiguousData( OwnedSlice, @@ -889,27 +873,19 @@ public: res.data() + res.size(), TContiguousData(res)); } else { + auto fullSize = size + headroom + tailroom; + NActors::TSharedData res = NActors::TSharedData::AttachUnsafe(TBackend::TSharedDataControllingOwner::Allocate(size, headroom, tailroom), fullSize); #ifdef KIKIMR_TRACE_CONTIGUOUS_DATA_GROW - NActors::TSharedData res = TBackTracingOwner::Allocate(TBackend::TCookies::BytesToAlloc(size + headroom + tailroom), TBackTracingOwner::INFO_ALLOC_UNINIT_ROOMS); -#else - NActors::TSharedData res = NActors::TSharedData::Uninitialized(TBackend::TCookies::BytesToAlloc(size + headroom + tailroom)); + TBackTracingOwner::FakeOwner(res, TBackTracingOwner::INFO_ALLOC_UNINIT_ROOMS); #endif - auto isAligned = [](const void * ptr, std::uintptr_t alignment) noexcept { - auto iptr = reinterpret_cast<std::uintptr_t>(ptr); - return !(iptr % alignment); - }; - char* place = res.mutable_data() + res.size() - sizeof(TBackend::TCookies); - Y_VERIFY(isAligned(place, alignof(TBackend::TCookies))); - TBackend::TCookies* cookies = new(place) TBackend::TCookies(); - - return TContiguousData( - OwnedSlice, - res.data() + headroom, - res.data() + headroom + size, - TContiguousData(res, cookies, TBackend::ControlToken)); + return TContiguousData(res, res.data() + headroom, size, TBackend::ControlToken); } } + static NActors::TSharedData UninitializedSharedData(size_t size) { + return NActors::TSharedData::AttachUnsafe(TBackend::TSharedDataControllingOwner::Allocate(size), size); + } + template <class TType> bool ContainsNativeType() const { return Backend.ContainsNativeType<TType>(); @@ -1088,7 +1064,6 @@ public: void Trim(size_t size, size_t frontOffset = 0) { Y_VERIFY(size <= End - Begin - frontOffset); - Backend.Disown(); Begin = Begin + frontOffset; End = Begin + size; } diff --git a/library/cpp/actors/util/contiguous_data_ut.cpp b/library/cpp/actors/util/contiguous_data_ut.cpp index f2378a4775..b7b9029f85 100644 --- a/library/cpp/actors/util/contiguous_data_ut.cpp +++ b/library/cpp/actors/util/contiguous_data_ut.cpp @@ -54,27 +54,27 @@ Y_UNIT_TEST_SUITE(TContiguousData) { TContiguousData data = TContiguousData::Uninitialized(10, 20, 30); UNIT_ASSERT_EQUAL(data.size(), 10); UNIT_ASSERT_EQUAL(data.Headroom(), 20); - UNIT_ASSERT_EQUAL(data.Tailroom(), 34); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom() + 2 * sizeof(char*)); + UNIT_ASSERT_EQUAL(data.Tailroom(), 30); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom()); data.GrowFront(5); UNIT_ASSERT_EQUAL(data.size(), 15); UNIT_ASSERT_EQUAL(data.Headroom(), 15); - UNIT_ASSERT_EQUAL(data.Tailroom(), 34); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom() + 2 * sizeof(char*)); + UNIT_ASSERT_EQUAL(data.Tailroom(), 30); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom()); data.GrowBack(5); UNIT_ASSERT_EQUAL(data.size(), 20); UNIT_ASSERT_EQUAL(data.Headroom(), 15); - UNIT_ASSERT_EQUAL(data.Tailroom(), 29); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom() + 2 * sizeof(char*)); + UNIT_ASSERT_EQUAL(data.Tailroom(), 25); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom()); data.GrowFront(21); UNIT_ASSERT_EQUAL(data.size(), 41); UNIT_ASSERT_EQUAL(data.Headroom(), 0); - UNIT_ASSERT_EQUAL(data.Tailroom(), 31); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 88); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom() + 2 * sizeof(char*)); + UNIT_ASSERT_EQUAL(data.Tailroom(), 25); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 66); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), data.size() + data.Headroom() + data.Tailroom()); data.GrowBack(32); UNIT_ASSERT_EQUAL(data.size(), 73); UNIT_ASSERT_EQUAL(data.Headroom(), 0); @@ -89,30 +89,30 @@ Y_UNIT_TEST_SUITE(TContiguousData) { UNIT_ASSERT_EQUAL(data.data(), otherData.data()); UNIT_ASSERT_EQUAL(data.size(), 10); UNIT_ASSERT_EQUAL(data.Headroom(), 20); - UNIT_ASSERT_EQUAL(data.Tailroom(), 34); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80); + UNIT_ASSERT_EQUAL(data.Tailroom(), 30); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60); UNIT_ASSERT_EQUAL(otherData.size(), 10); UNIT_ASSERT_EQUAL(otherData.Headroom(), 20); - UNIT_ASSERT_EQUAL(otherData.Tailroom(), 34); - UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 80); + UNIT_ASSERT_EQUAL(otherData.Tailroom(), 30); + UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 60); data.GrowFront(5); data.GrowBack(5); UNIT_ASSERT_EQUAL(data.data() + 5, otherData.data()); UNIT_ASSERT_EQUAL(data.size(), 20); UNIT_ASSERT_EQUAL(data.Headroom(), 15); - UNIT_ASSERT_EQUAL(data.Tailroom(), 29); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80); + UNIT_ASSERT_EQUAL(data.Tailroom(), 25); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60); otherData.GrowFront(5); UNIT_ASSERT_UNEQUAL(data.data(), otherData.data()); UNIT_ASSERT_EQUAL(otherData.size(), 15); UNIT_ASSERT_EQUAL(otherData.Headroom(), 15); - UNIT_ASSERT_EQUAL(otherData.Tailroom(), 34); - UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 80); + UNIT_ASSERT_EQUAL(otherData.Tailroom(), 30); + UNIT_ASSERT_EQUAL(otherData.GetOccupiedMemorySize(), 60); data.Trim(10, 5); UNIT_ASSERT_EQUAL(data.size(), 10); UNIT_ASSERT_EQUAL(data.Headroom(), 20); - UNIT_ASSERT_EQUAL(data.Tailroom(), 34); - UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 80); + UNIT_ASSERT_EQUAL(data.Tailroom(), 30); + UNIT_ASSERT_EQUAL(data.GetOccupiedMemorySize(), 60); } Y_UNIT_TEST(Trim) { @@ -120,7 +120,7 @@ Y_UNIT_TEST_SUITE(TContiguousData) { TContiguousData otherData(data); otherData.Trim(5); UNIT_ASSERT_EQUAL(data.data(), otherData.data()); - UNIT_ASSERT_EQUAL(otherData.Headroom(), 0); + UNIT_ASSERT_EQUAL(otherData.Headroom(), 20); UNIT_ASSERT_EQUAL(otherData.Tailroom(), 0); TContiguousData otherData2(data); otherData2.Trim(1, 1); @@ -146,7 +146,7 @@ Y_UNIT_TEST_SUITE(TContiguousData) { Y_UNIT_TEST(SliceUnshare) { TContiguousData data = TContiguousData::Uninitialized(10, 20, 30); - TContiguousData otherData(TContiguousData::Slice, data.data(), data.size(), data); + TContiguousData otherData(TContiguousData::Slice, data.data() + 1, data.size() - 2, data); UNIT_ASSERT_EQUAL(otherData.Headroom(), 0); UNIT_ASSERT_EQUAL(otherData.Tailroom(), 0); } diff --git a/library/cpp/actors/util/shared_data_backtracing_owner.h b/library/cpp/actors/util/shared_data_backtracing_owner.h index 9e93e327c3..ea479d5fd1 100644 --- a/library/cpp/actors/util/shared_data_backtracing_owner.h +++ b/library/cpp/actors/util/shared_data_backtracing_owner.h @@ -24,7 +24,7 @@ public: static constexpr const char* INFO_ALLOC_UNINITIALIZED = "ALLOC_UNINITIALIZED"; static constexpr const char* INFO_ALLOC_UNINIT_ROOMS = "ALLOC_UNINIT_ROOMS"; - static NActors::TSharedData Allocate(size_t size, const char* info = nullptr) { + static char* Allocate(size_t size, const char* info = nullptr) { char* raw = reinterpret_cast<char*>(y_allocate(OverheadSize + size)); THeader* header = reinterpret_cast<THeader*>(raw + PrivateHeaderSize); TSelf* btOwner = new TSelf; @@ -33,7 +33,7 @@ public: header->RefCount = 1; header->Owner = btOwner; char* data = raw + OverheadSize; - return NActors::TSharedData::AttachUnsafe(data, size); + return data; } static void FakeOwner(const NActors::TSharedData& data, const char* info = nullptr) { @@ -68,6 +68,10 @@ public: delete this; } + IOwner* GetRealOwner() const { + return RealOwner; + } + void PrintBackTrace() { Cerr << "Deallocate TSharedData with info# " << Info << Endl; BackTrace.PrintTo(Cerr); |