-
Notifications
You must be signed in to change notification settings - Fork 0
Optimize IndexCount to terminate slaves early when limit exceeded #150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ | |
| #include "jfile.hpp" | ||
| #include "jtime.hpp" | ||
| #include "jsort.hpp" | ||
| #include <atomic> | ||
|
|
||
| #include "rtlkey.hpp" | ||
| #include "jhtree.hpp" | ||
|
|
@@ -1273,6 +1274,8 @@ class CIndexCountSlaveActivity : public CIndexReadSlaveBase | |
| rowcount_t preknownTotalCount = 0; | ||
| bool totalCountKnown = false; | ||
| bool done = false; | ||
| mptag_t stopTag = TAG_NULL; | ||
| std::atomic<bool> stopped{false}; | ||
|
|
||
| bool checkKeyedLimit() | ||
| { | ||
|
|
@@ -1285,12 +1288,41 @@ class CIndexCountSlaveActivity : public CIndexReadSlaveBase | |
| } | ||
| return true; | ||
| } | ||
| bool checkStopSignal() | ||
| { | ||
| // For IndexExists (choosenLimit == 1), check if master signaled us to stop | ||
| if (stopped.load(std::memory_order_relaxed)) | ||
| return true; | ||
|
|
||
| if (choosenLimit == 1 && stopTag != TAG_NULL) | ||
| { | ||
| // Non-blocking check for stop signal | ||
| CMessageBuffer msg; | ||
| if (container.queryJobChannel().queryJobComm().recv(msg, 0, stopTag, nullptr, 0)) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copilot - this approach won't work. Even if this was non-blocking (which it isn't), it is too inefficient for the caller of checkStopSignal() to do this each call.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Refactored to use a dedicated async |
||
| { | ||
| bool stopFlag; | ||
| msg.read(stopFlag); | ||
| if (stopFlag) | ||
| { | ||
| stopped.store(true, std::memory_order_relaxed); | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| public: | ||
| CIndexCountSlaveActivity(CGraphElementBase *_container) : CIndexReadSlaveBase(_container) | ||
| { | ||
| helper = static_cast <IHThorIndexCountArg *> (container.queryHelper()); | ||
| appendOutputLinked(this); | ||
| } | ||
| virtual void init(MemoryBuffer &data, MemoryBuffer &slaveData) override | ||
| { | ||
| PARENT::init(data, slaveData); | ||
| // Always read stopTag (will be TAG_NULL for non-IndexExists or local/grouped cases) | ||
| data.read(stopTag); | ||
| } | ||
| virtual void prepareManager(IKeyManager *manager) override | ||
| { | ||
| PARENT::prepareManager(manager); | ||
|
|
@@ -1323,6 +1355,7 @@ class CIndexCountSlaveActivity : public CIndexReadSlaveBase | |
| preknownTotalCount = 0; | ||
| } | ||
| done = false; | ||
| stopped.store(false, std::memory_order_relaxed); | ||
| } | ||
|
|
||
| // IRowStream | ||
|
|
@@ -1371,11 +1404,17 @@ class CIndexCountSlaveActivity : public CIndexReadSlaveBase | |
| callback.finishedRow(); | ||
| if ((totalCount > choosenLimit)) | ||
| break; | ||
| // For IndexExists, check if master signaled us to stop | ||
| if (checkStopSignal()) | ||
| break; | ||
| } | ||
| if (keyManager) | ||
| resetManager(keyManager); | ||
| if ((totalCount > choosenLimit)) | ||
| break; | ||
| // For IndexExists, check if master signaled us to stop | ||
| if (checkStopSignal()) | ||
| break; | ||
| } | ||
| if (_currentManager) | ||
| prepareManager(_currentManager); | ||
|
|
@@ -1435,6 +1474,8 @@ class CIndexCountSlaveActivity : public CIndexReadSlaveBase | |
| { | ||
| CIndexReadSlaveBase::abort(); | ||
| cancelReceiveMsg(0, mpTag); | ||
| if (stopTag != TAG_NULL) | ||
| cancelReceiveMsg(0, stopTag); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot - In fact, this should not be the basis of stopping early.
In all cases, if the limit is exceeded, the master should signal to the workers that they can stop to save them wasting their time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modified to send stop signals whenever ANY choosenLimit is exceeded (not just choosenLimit==1). The master now checks
total > choosenLimitin the overriddenaggregateToLimit()method, making this optimization broadly applicable to CHOOSEN, IndexExists, and any other operation with a limit. See commit for details.