diff --git a/documentation/tutorial/tutorial.actor.cpp b/documentation/tutorial/tutorial.actor.cpp index 4213ddd5c2..6fc0f18823 100644 --- a/documentation/tutorial/tutorial.actor.cpp +++ b/documentation/tutorial/tutorial.actor.cpp @@ -396,15 +396,15 @@ ACTOR Future fdbStatusStresser() { std::unordered_map()>> actors = { { "timer", &simpleTimer }, // ./tutorial timer - { "promiseDemo", &promiseDemo }, // ./tutorial promiseDemo - { "triggerDemo", &triggerDemo }, // ./tutorial triggerDemo - { "echoServer", &echoServer }, // ./tutorial -p 6666 echoServer - { "echoClient", &echoClient }, // ./tutorial -s 127.0.0.1:6666 echoClient - { "kvStoreServer", &kvStoreServer }, // ./tutorial -p 6666 kvStoreServer - { "kvSimpleClient", &kvSimpleClient }, // ./tutorial -s 127.0.0.1:6666 kvSimpleClient - { "multipleClients", &multipleClients }, // ./tutorial -s 127.0.0.1:6666 multipleClients - { "fdbClient", &fdbClient }, // ./tutorial -C $CLUSTER_FILE_PATH fdbClient - { "fdbStatusStresser", &fdbStatusStresser } + // { "promiseDemo", &promiseDemo }, // ./tutorial promiseDemo + // { "triggerDemo", &triggerDemo }, // ./tutorial triggerDemo + // { "echoServer", &echoServer }, // ./tutorial -p 6666 echoServer + // { "echoClient", &echoClient }, // ./tutorial -s 127.0.0.1:6666 echoClient + // { "kvStoreServer", &kvStoreServer }, // ./tutorial -p 6666 kvStoreServer + // { "kvSimpleClient", &kvSimpleClient }, // ./tutorial -s 127.0.0.1:6666 kvSimpleClient + // { "multipleClients", &multipleClients }, // ./tutorial -s 127.0.0.1:6666 multipleClients + // { "fdbClient", &fdbClient }, // ./tutorial -C $CLUSTER_FILE_PATH fdbClient + // { "fdbStatusStresser", &fdbStatusStresser } }; // ./tutorial -C $CLUSTER_FILE_PATH fdbStatusStresser int main(int argc, char* argv[]) { diff --git a/fdbclient/ActorLineageProfiler.cpp b/fdbclient/ActorLineageProfiler.cpp index 9fadf95127..1e3543c0a6 100644 --- a/fdbclient/ActorLineageProfiler.cpp +++ b/fdbclient/ActorLineageProfiler.cpp @@ -29,6 +29,11 @@ using namespace std::literals; +// TODO: For debugging, remove +LineageReference* curLineage() { + return currentLineage; +} + class Packer : public msgpack::packer { struct visitor_t { using VisitorMap = std::unordered_map>; @@ -244,8 +249,15 @@ std::vector> SampleCollection_t::get(double from /*= 0.0 return res; } -void sample(const Reference& lineage) { - boost::asio::post(ActorLineageProfiler::instance().context(), [lineage]() { +// void sample(const Reference& lineage) { +void sample(Reference* ptr) { + // boost::asio::post(ActorLineageProfiler::instance().context(), [lineage]() { + // SampleCollection::instance().collect(lineage); + // }); + if (!ptr->isValid()) { + return; + } + boost::asio::post(ActorLineageProfiler::instance().context(), [lineage = Reference::addRef(ptr->getPtr())]() { SampleCollection::instance().collect(lineage); }); } diff --git a/fdbclient/ActorLineageProfiler.h b/fdbclient/ActorLineageProfiler.h index 4e6f0bbd3d..136eea9390 100644 --- a/fdbclient/ActorLineageProfiler.h +++ b/fdbclient/ActorLineageProfiler.h @@ -34,6 +34,9 @@ void samplingProfilerUpdateFrequency(std::optional freq); void samplingProfilerUpdateWindow(std::optional window); +// TODO: For debugging, remove +LineageReference* curLineage(); + struct IALPCollectorBase { virtual std::optional collect(ActorLineage*) = 0; virtual const std::string_view& name() = 0; diff --git a/fdbclient/StackLineage.cpp b/fdbclient/StackLineage.cpp index 442ced3f82..b1731b879c 100644 --- a/fdbclient/StackLineage.cpp +++ b/fdbclient/StackLineage.cpp @@ -21,7 +21,7 @@ #include "fdbclient/StackLineage.h" std::vector getActorStackTrace() { - return currentLineage->stack(&StackLineage::actorName); + return (*currentLineage)->stack(&StackLineage::actorName); } namespace { diff --git a/flow/FastRef.h b/flow/FastRef.h index 06221e4cc0..487f7cb53a 100644 --- a/flow/FastRef.h +++ b/flow/FastRef.h @@ -194,4 +194,14 @@ bool operator!=(const Reference

& lhs, const Reference

& rhs) { return !(lhs == rhs); } +template +class LineageReference : public Reference

{ +// TODO: Make private +public: + LineageReference() : Reference

(nullptr), referencesSelf(false) {} + explicit LineageReference(P* ptr) : Reference

(ptr), referencesSelf(false) {} + LineageReference(const LineageReference& r) : Reference

(r), referencesSelf(false) {} + bool referencesSelf; +}; + #endif diff --git a/flow/Net2.actor.cpp b/flow/Net2.actor.cpp index 3ae9136efb..b229210eeb 100644 --- a/flow/Net2.actor.cpp +++ b/flow/Net2.actor.cpp @@ -1435,7 +1435,9 @@ void Net2::run() { checkForSlowTask(tscBegin, timestampCounter(), taskEnd - taskBegin, TaskPriority::RunCycleFunction); } - replaceLineage(Reference()); + // replaceLineage(LineageReference()); + // currentLineage = nullptr; + // replaceLineage(nullptr); double sleepTime = 0; bool b = ready.empty(); if (b) { diff --git a/flow/actorcompiler/ActorCompiler.cs b/flow/actorcompiler/ActorCompiler.cs index db923ddd4b..f5b1e456af 100644 --- a/flow/actorcompiler/ActorCompiler.cs +++ b/flow/actorcompiler/ActorCompiler.cs @@ -452,8 +452,8 @@ namespace actorcompiler fullClassName, string.Join(", ", actor.parameters.Select(p => p.name).ToArray())); - if (actor.IsCancellable()) - writer.WriteLine("\trestore_lineage _;"); + // if (actor.IsCancellable()) + // writer.WriteLine("\trestore_lineage _;"); if (actor.returnType != null) writer.WriteLine("\treturn Future<{1}>({0});", newActor, actor.returnType); else @@ -1288,6 +1288,8 @@ namespace actorcompiler constructor.WriteLine("{"); constructor.Indent(+1); ProbeEnter(constructor, actor.name); + constructor.WriteLine("CurrentLineageReplace _(&this->lineage);"); + // constructor.WriteLine("getCurrentLineage()->modify(&StackLineage::actorName) = LiteralStringRef(\"{0}\");", actor.name); constructor.WriteLine("this->{0};", body.call()); ProbeExit(constructor, actor.name); WriteFunction(writer, constructor, constructor.BodyText); diff --git a/flow/flow.cpp b/flow/flow.cpp index b3f7bba02a..1d38745892 100644 --- a/flow/flow.cpp +++ b/flow/flow.cpp @@ -26,12 +26,17 @@ #include #include + +LineageReference rootLineage; std::atomic startSampling = false; -thread_local Reference currentLineage; +// TODO: Fix this (ideally get rid of allocation, otherwise memory leak?) +thread_local LineageReference* currentLineage = &rootLineage;//new LineageReference(); LineagePropertiesBase::~LineagePropertiesBase() {} -ActorLineage::ActorLineage() : properties(), parent(currentLineage) {} +ActorLineage::ActorLineage() : properties(), parent(*currentLineage) { + // TraceEvent("LUKAS_ActorLineage").detail("CurrentLineagePtr", reinterpret_cast(currentLineage)).detail("CurrentLineageRefPtr", reinterpret_cast(currentLineage->getPtr())); +} ActorLineage::~ActorLineage() { for (auto property : properties) { @@ -40,19 +45,53 @@ ActorLineage::~ActorLineage() { } Reference getCurrentLineage() { - if (!currentLineage.isValid() || currentLineage == currentLineage->getParent()) { - replaceLineage(Reference{ new ActorLineage() }); + // if (!currentLineage.isValid()/* || currentLineage == currentLineage->getParent()*/) { + if (!currentLineage->isValid() || !currentLineage->referencesSelf) { + // replaceLineage(LineageReference{ new ActorLineage() }); + // *currentLineage = LineageReference{ new ActorLineage() }; + + // ActorLineage* lineage = new ActorLineage(); + // *currentLineage = LineageReference::addRef(lineage); + // *currentLineage = LineageReference(new ActorLineage()); + // currentLineage->referencesSelf = true; + // TraceEvent("LUKAS_getCurrent").detail("Ptr", reinterpret_cast(currentLineage->getPtr())); + + currentLineage->setPtrUnsafe(new ActorLineage()); + currentLineage->referencesSelf = true; } - return currentLineage; + return *currentLineage; } -void sample(const Reference& lineage); +// void sample(const Reference& lineage); +void sample(Reference* ptr); -void replaceLineage(Reference lineage) { +void replaceLineage(LineageReference* lineage) { + // if (lineage.isValid()) { + // auto name = lineage->get(&StackLineage::actorName); + // if (name.has_value()) { + // TraceEvent("LUKAS_replaceLineage").detail("Name", name.value()); + // } + // } + // if (currentLineage->isValid()) { + // auto name = (*currentLineage)->get(&StackLineage::actorName); + // if (name.has_value()) { + // TraceEvent("LUKAS_replaceLineageCurrentLineage").detail("Name", name.value()); + // } + // } + // TraceEvent("LUKAS_replaceLineage").detail("Ptr", reinterpret_cast(lineage)); + // TraceEvent("LUKAS_replaceLineage2").detail("IsValid", lineage->isValid()).detail("PtrPtr", reinterpret_cast(lineage->getPtr())); if (!startSampling) { currentLineage = lineage; } else { startSampling = false; + // if (currentLineage->isValid()) { + // std::string stack = ""; + // auto vec = (*currentLineage)->stack(&StackLineage::actorName); + // for (const auto& str : vec) { + // stack += std::string(reinterpret_cast(str.begin()), str.size()) + " "; + // } + // TraceEvent("LUKAS_replaceLineage").detail("Stack", stack); + // } sample(currentLineage); currentLineage = lineage; } diff --git a/flow/flow.h b/flow/flow.h index da1db72af7..de3861c283 100644 --- a/flow/flow.h +++ b/flow/flow.h @@ -448,7 +448,7 @@ struct LineageProperties : LineagePropertiesBase { } }; -struct ActorLineage : ThreadUnsafeReferenceCounted { +struct ActorLineage : ThreadSafeReferenceCounted { friend class LocalLineage; struct Property { @@ -541,7 +541,8 @@ public: }; extern std::atomic startSampling; -extern thread_local Reference currentLineage; +// TODO: ThreadUnsafe? +extern thread_local LineageReference* currentLineage; struct StackLineage : LineageProperties { static const std::string_view name; @@ -549,25 +550,35 @@ struct StackLineage : LineageProperties { }; Reference getCurrentLineage(); -void replaceLineage(Reference lineage); +void replaceLineage(LineageReference* lineage); // This class can be used in order to modify all lineage properties // of actors created within a (non-actor) scope struct LocalLineage { - Reference lineage = Reference{ new ActorLineage() }; - Reference oldLineage; + LineageReference lineage = LineageReference{ new ActorLineage() }; + LineageReference* oldLineage; LocalLineage() { oldLineage = currentLineage; - replaceLineage(lineage); + replaceLineage(&lineage); } ~LocalLineage() { replaceLineage(oldLineage); } }; +// TODO: No longer want this because we are now setting a global instead of just the field in a class struct restore_lineage { - Reference prev; - restore_lineage() : prev(currentLineage) {} + // Reference lineage; + LineageReference* prev; + // LineageReference prev; + // restore_lineage() : prev(*currentLineage) { + restore_lineage() : prev(currentLineage) { + // if (currentLineage != nullptr && currentLineage->isValid()) { + // prev = *currentLineage; + // } + // prev = currentLineage; + // replaceLineage(lineage); + } ~restore_lineage() { replaceLineage(prev); } @@ -1148,53 +1159,104 @@ static inline void destruct(T& t) { t.~T(); } +// TODO: Rename, move to better spot (above) +struct CurrentLineageReplace { + LineageReference* oldLineage; + CurrentLineageReplace(LineageReference* with) : oldLineage(currentLineage) { + // currentLineage = with; + replaceLineage(with); + } + ~CurrentLineageReplace() { + // currentLineage = oldLineage; + replaceLineage(oldLineage); + } +}; + template struct Actor : SAV { - Reference lineage = currentLineage; + // LineageReference* prev = currentLineage; + LineageReference lineage = *currentLineage; + // Reference lineage; int8_t actor_wait_state; // -1 means actor is cancelled; 0 means actor is not waiting; 1-N mean waiting in callback // group # Actor() : SAV(1, 1), actor_wait_state(0) { /*++actorCount;*/ - replaceLineage(lineage); + // if (currentLineage != nullptr && currentLineage->isValid()) { + // lineage = *currentLineage; + // } + // replaceLineage(&lineage); + // lineage.referencesSelf = false; + // currentLineage = &lineage; + } + ~Actor() { + //--actorCount; + // replaceLineage(new LineageReference()); + // replaceLineage(prev); } - //~Actor() { --actorCount; } Reference setLineage() { - auto res = currentLineage; - replaceLineage(lineage); + Reference res = *currentLineage; + // if (currentLineage != nullptr && currentLineage->isValid()) { + // res = *currentLineage; + // } + replaceLineage(&lineage); return res; } + + LineageReference* lineageAddr() { + return std::addressof(lineage); + } }; template <> struct Actor { // This specialization is for a void actor (one not returning a future, hence also uncancellable) - Reference lineage = currentLineage; + // LineageReference* prev = currentLineage; + LineageReference lineage = *currentLineage; + // Reference lineage; int8_t actor_wait_state; // 0 means actor is not waiting; 1-N mean waiting in callback group # Actor() : actor_wait_state(0) { /*++actorCount;*/ - replaceLineage(lineage); + // if (currentLineage != nullptr && currentLineage->isValid()) { + // lineage = *currentLineage; + // } + // replaceLineage(&lineage); + // lineage.referencesSelf = false; + // currentLineage = &lineage; + } + ~Actor() { + //--actorCount; + // replaceLineage(new LineageReference()); + // replaceLineage(prev); } - //~Actor() { --actorCount; } Reference setLineage() { - auto res = currentLineage; - replaceLineage(lineage); + Reference res = *currentLineage; + // if (currentLineage != nullptr && currentLineage->isValid()) { + // res = *currentLineage; + // } + replaceLineage(&lineage); return res; } + + LineageReference* lineageAddr() { + return std::addressof(lineage); + } }; template struct ActorCallback : Callback { virtual void fire(ValueType const& value) override { - auto _ = static_cast(this)->setLineage(); + // auto _ = static_cast(this)->setLineage(); + CurrentLineageReplace _(static_cast(this)->lineageAddr()); static_cast(this)->a_callback_fire(this, value); } virtual void error(Error e) override { - auto _ = static_cast(this)->setLineage(); + // auto _ = static_cast(this)->setLineage(); + CurrentLineageReplace _(static_cast(this)->lineageAddr()); static_cast(this)->a_callback_error(this, e); } }; @@ -1202,15 +1264,18 @@ struct ActorCallback : Callback { template struct ActorSingleCallback : SingleCallback { void fire(ValueType const& value) override { - auto _ = static_cast(this)->setLineage(); + // auto _ = static_cast(this)->setLineage(); + CurrentLineageReplace _(static_cast(this)->lineageAddr()); static_cast(this)->a_callback_fire(this, value); } void fire(ValueType&& value) override { - auto _ = static_cast(this)->setLineage(); + // auto _ = static_cast(this)->setLineage(); + CurrentLineageReplace _(static_cast(this)->lineageAddr()); static_cast(this)->a_callback_fire(this, std::move(value)); } void error(Error e) override { - auto _ = static_cast(this)->setLineage(); + // auto _ = static_cast(this)->setLineage(); + CurrentLineageReplace _(static_cast(this)->lineageAddr()); static_cast(this)->a_callback_error(this, e); } }; diff --git a/flow/genericactors.actor.h b/flow/genericactors.actor.h index baf041e0b5..a11dc723d4 100644 --- a/flow/genericactors.actor.h +++ b/flow/genericactors.actor.h @@ -1566,6 +1566,10 @@ struct YieldedFutureActor : SAV, ActorCallback setLineage() { + return *currentLineage; + } + + LineageReference* lineageAddr() { return currentLineage; }