summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthenewone <[email protected]>2025-08-04 20:25:02 +0300
committerthenewone <[email protected]>2025-08-04 21:30:57 +0300
commit140e5db975aa31e2326abb3b5bd58a6e142075c6 (patch)
tree48258c7ab5d06aea1a36cab4a568bd9f044394f4
parent77ae0a1260666d7ad2baf248ecd24200b337dd4d (diff)
Don't construct twice yson struct members of yson struct lite type
There is a serious problem of all yson structs: their members are constructed twice when the yson struct is constructing: the first time implicitly as common members, and the second time explicitly right in yson struct constructor's body. So if any yson struct A has a member of yson struct lite type B, then per one A's construction the B will be constructed twice. If in turn B has a member of yson struct lite type C then it will be contructed two time per B's contruction and four times per A's construction. The next level D will be constructed 8 times etc, generally giving compexity of 2^N for construction of yson struct lite chain of length N. This patch solves the most common case when yson struct lite member is declared as .Default() or .Otional(). In this case ther's no need to construct the member the second time. This gives improvement from: ``` BenchmarkDecode<TDeepStructLite> 88384 ns 88365 ns 7578 items_per_second=11.3167k/s ``` To: ``` BenchmarkDecode<TDeepStructLite> 35361 ns 35359 ns 19786 items_per_second=28.2814k/s ``` Part 3 of https://nda.ya.ru/t/E9Ji-1bm7Gwv6c commit_hash:b8a3db2cdc4393bae38b7310047cc3fcd9b9a15c
-rw-r--r--yt/yt/core/ytree/yson_struct-inl.h2
-rw-r--r--yt/yt/core/ytree/yson_struct.cpp6
-rw-r--r--yt/yt/core/ytree/yson_struct.h2
-rw-r--r--yt/yt/core/ytree/yson_struct_detail-inl.h8
-rw-r--r--yt/yt/core/ytree/yson_struct_detail.cpp4
-rw-r--r--yt/yt/core/ytree/yson_struct_detail.h9
6 files changed, 16 insertions, 15 deletions
diff --git a/yt/yt/core/ytree/yson_struct-inl.h b/yt/yt/core/ytree/yson_struct-inl.h
index 9ef10db1b53..423d287f372 100644
--- a/yt/yt/core/ytree/yson_struct-inl.h
+++ b/yt/yt/core/ytree/yson_struct-inl.h
@@ -453,7 +453,7 @@ private: \
if (std::type_index(typeid(TStruct)) == this->FinalType_) { \
::NYT::NYTree::TYsonStructRegistry::Get()->OnFinalCtorCalled(); \
if (!::NYT::NYTree::TYsonStructRegistry::Get()->InitializationInProgress()) { \
- this->SetDefaults(); \
+ this->SetDefaults(/*dontSetLiteMembers*/ true); \
} \
} \
diff --git a/yt/yt/core/ytree/yson_struct.cpp b/yt/yt/core/ytree/yson_struct.cpp
index e4a6b30df76..d3294f3754d 100644
--- a/yt/yt/core/ytree/yson_struct.cpp
+++ b/yt/yt/core/ytree/yson_struct.cpp
@@ -181,10 +181,10 @@ void TYsonStructBase::Postprocess(const std::function<NYPath::TYPath()>& pathGet
Meta_->PostprocessStruct(this, pathGetter);
}
-void TYsonStructBase::SetDefaults()
+void TYsonStructBase::SetDefaults(bool dontSetLiteMembers)
{
YT_VERIFY(Meta_);
- Meta_->SetDefaultsOfInitializedStruct(this);
+ Meta_->SetDefaultsOfInitializedStruct(this, dontSetLiteMembers);
}
void TYsonStructBase::SaveParameter(const std::string& key, IYsonConsumer* consumer) const
@@ -236,7 +236,7 @@ void TYsonStruct::InitializeRefCounted()
{
TYsonStructRegistry::Get()->OnFinalCtorCalled();
if (!TYsonStructRegistry::InitializationInProgress()) {
- SetDefaults();
+ SetDefaults(/*dontSetLiteMembers*/ true);
}
}
diff --git a/yt/yt/core/ytree/yson_struct.h b/yt/yt/core/ytree/yson_struct.h
index 7cceb5a2288..4cebefa3234 100644
--- a/yt/yt/core/ytree/yson_struct.h
+++ b/yt/yt/core/ytree/yson_struct.h
@@ -92,7 +92,7 @@ public:
void Postprocess(const std::function<NYPath::TYPath()>& pathGetter = {});
- void SetDefaults();
+ void SetDefaults(bool dontSetLiteMembers = false);
void Save(NYson::IYsonConsumer* consumer) const;
diff --git a/yt/yt/core/ytree/yson_struct_detail-inl.h b/yt/yt/core/ytree/yson_struct_detail-inl.h
index d6ddccb63d1..0bdfa8a58da 100644
--- a/yt/yt/core/ytree/yson_struct_detail-inl.h
+++ b/yt/yt/core/ytree/yson_struct_detail-inl.h
@@ -929,11 +929,10 @@ void TYsonStructParameter<TValue>::PostprocessParameter(const TYsonStructBase* s
}
template <class TValue>
-void TYsonStructParameter<TValue>::SetDefaultsInitialized(TYsonStructBase* self)
+void TYsonStructParameter<TValue>::SetDefaultsInitialized(TYsonStructBase* self, bool dontSetLiteMembers)
{
- TValue& value = FieldAccessor_->GetValue(self);
-
- if (DefaultCtor_) {
+ if (DefaultCtor_ && !(std::is_base_of_v<TYsonStructLite, TValue> && dontSetLiteMembers && DefaultIsDefaultConstruction_)) {
+ TValue& value = FieldAccessor_->GetValue(self);
value = (*DefaultCtor_)();
}
}
@@ -1027,6 +1026,7 @@ TYsonStructParameter<TValue>& TYsonStructParameter<TValue>::Optional(bool init)
if (init) {
DefaultCtor_ = [] () { return TValue{}; };
+ DefaultIsDefaultConstruction_ = true;
}
return *this;
diff --git a/yt/yt/core/ytree/yson_struct_detail.cpp b/yt/yt/core/ytree/yson_struct_detail.cpp
index 8133575cd5a..14581c948df 100644
--- a/yt/yt/core/ytree/yson_struct_detail.cpp
+++ b/yt/yt/core/ytree/yson_struct_detail.cpp
@@ -27,14 +27,14 @@ bool ShouldThrow(EUnrecognizedStrategy strategy)
////////////////////////////////////////////////////////////////////////////////
-void TYsonStructMeta::SetDefaultsOfInitializedStruct(TYsonStructBase* target) const
+void TYsonStructMeta::SetDefaultsOfInitializedStruct(TYsonStructBase* target, bool dontSetLiteMembers) const
{
if (auto* bitmap = target->GetSetFieldsBitmap()) {
bitmap->Initialize(ssize(Parameters_));
}
for (const auto& [_, parameter] : SortedParameters_) {
- parameter->SetDefaultsInitialized(target);
+ parameter->SetDefaultsInitialized(target, dontSetLiteMembers);
}
for (const auto& preprocessor : Preprocessors_) {
diff --git a/yt/yt/core/ytree/yson_struct_detail.h b/yt/yt/core/ytree/yson_struct_detail.h
index b2a9c5ae14d..c074786dc2e 100644
--- a/yt/yt/core/ytree/yson_struct_detail.h
+++ b/yt/yt/core/ytree/yson_struct_detail.h
@@ -94,7 +94,7 @@ struct IYsonStructParameter
virtual void PostprocessParameter(const TYsonStructBase* self, const std::function<NYPath::TYPath()>& pathGetter) const = 0;
- virtual void SetDefaultsInitialized(TYsonStructBase* self) = 0;
+ virtual void SetDefaultsInitialized(TYsonStructBase* self, bool dontSetLiteMembers = false) = 0;
virtual bool CanOmitValue(const TYsonStructBase* self) const = 0;
@@ -121,7 +121,7 @@ struct IYsonStructMeta
{
virtual const THashMap<std::string, IYsonStructParameterPtr>& GetParameterMap() const = 0;
virtual const std::vector<std::pair<std::string, IYsonStructParameterPtr>>& GetParameterSortedList() const = 0;
- virtual void SetDefaultsOfInitializedStruct(TYsonStructBase* target) const = 0;
+ virtual void SetDefaultsOfInitializedStruct(TYsonStructBase* target, bool dontSetLiteMembers = false) const = 0;
virtual const THashSet<std::string>& GetRegisteredKeys() const = 0;
virtual void PostprocessStruct(TYsonStructBase* target, const std::function<NYPath::TYPath()>& pathGetter) const = 0;
virtual IYsonStructParameterPtr GetParameter(const std::string& keyOrAlias) const = 0;
@@ -163,7 +163,7 @@ class TYsonStructMeta
: public IYsonStructMeta
{
public:
- void SetDefaultsOfInitializedStruct(TYsonStructBase* target) const override;
+ void SetDefaultsOfInitializedStruct(TYsonStructBase* target, bool dontSetLiteMembers = false) const override;
const THashMap<std::string, IYsonStructParameterPtr>& GetParameterMap() const override;
const std::vector<std::pair<std::string, IYsonStructParameterPtr>>& GetParameterSortedList() const override;
@@ -295,7 +295,7 @@ public:
const std::function<void()>& validate) override;
void PostprocessParameter(const TYsonStructBase* self, const std::function<NYPath::TYPath()>& pathGetter) const override;
- void SetDefaultsInitialized(TYsonStructBase* self) override;
+ void SetDefaultsInitialized(TYsonStructBase* self, bool dontSetLiteMembers = false) override;
void Save(const TYsonStructBase* self, NYson::IYsonConsumer* consumer) const override;
bool CanOmitValue(const TYsonStructBase* self) const override;
bool IsRequired() const override;
@@ -357,6 +357,7 @@ private:
std::unique_ptr<IYsonFieldAccessor<TValue>> FieldAccessor_;
std::optional<std::function<TValue()>> DefaultCtor_;
+ bool DefaultIsDefaultConstruction_ = false;
bool SerializeDefault_ = true;
std::vector<TValidator> Validators_;
std::vector<std::string> Aliases_;