-
Notifications
You must be signed in to change notification settings - Fork 40
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
Provide framework for generic lazily evaluated operation results #1350
base: master
Are you sure you want to change the base?
Conversation
src/engine/Operation.cpp
Outdated
result._resultPointer->resultTable()->idTable().numColumns(); | ||
LOG(DEBUG) << "Computed result of size " << resultNumRows << " x " | ||
<< resultNumCols << std::endl; | ||
} |
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.
Does this debug message provide any real benefit to make it worth somehow incorporating it into lazily evaluated operations?
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1350 +/- ##
==========================================
- Coverage 89.63% 89.35% -0.29%
==========================================
Files 343 345 +2
Lines 29951 30472 +521
Branches 3315 3393 +78
==========================================
+ Hits 26847 27227 +380
- Misses 1957 2063 +106
- Partials 1147 1182 +35 ☔ View full report in Codecov by Sentry. |
This PR contains all the changes from the infrastructure for lazy operation evaluation (#1350) that are simple and repetitive, but touch many files. In particular: * Rename the `ResultTable` class to `Result` (a TODO suggested by @hannahbast some time ago). * Add a new parameter `bool requestLaziness` to `Operation::computeResult`. This parameter is currently unused.
updateRuntimeInformationOnSuccess( | ||
*resultAndCacheStatus._resultPointer->resultTable(), | ||
// TODO<RobinTF> find a better representation for "unknown" than 0. |
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.
This concept doesn't 100% make sense for lazy evaluation. We could of course provide a lower bound for qlever-ui to display by adding this to the onSizeChanged listener or something
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.
For now this is not the primary concern:)
@@ -38,6 +37,8 @@ class WaitedForResultWhichThenFailedException : public std::exception { | |||
enum struct CacheStatus { | |||
cachedNotPinned, | |||
cachedPinned, | |||
// TODO<RobinTF> Rename to notCached, the name is just confusing. Can | |||
// potentially be merged with notInCacheAndNotComputed. |
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.
Task for a follow-up PR
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.
A first round of comments.
I haven't looked at the whole caching stuff yet.
return; | ||
} | ||
if (masterState_ == MasterIteratorState::MASTER_STARTED && !isMaster) { | ||
conditionVariable_.wait(lock, [this, index]() { |
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.
You should implement a time limit here, especially if you synchronously block a thread here.
We need to handle the case of slow masters. I still think that the easiest way to do this is that also the master can receive a IteratorExpired
because there is no conceptual difference between a master and a non-master.
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.
I agree on the time limit, but as I told you in person the master/slave system does have some benefits so having only slaves pass a time limit would be an option, but this might be a task for a follow-up PR.
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.
I still think that the non-master approach + everybody having a timeout is better. We can probably dispute this further, the current state (forever blocking until the slow master times out) is a blocker for this PR.
sortedBy_{std::move(sortedBy)}, | ||
localVocab_{std::move(localVocab)} {} | ||
|
||
bool isDataEvaluated() const noexcept { |
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.
isn't this rather isMaterialized
as opposed to isLazy
?
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.
The name can be changed to everything you want once everything else is settled
updateRuntimeInformationOnSuccess( | ||
*resultAndCacheStatus._resultPointer->resultTable(), | ||
// TODO<RobinTF> find a better representation for "unknown" than 0. |
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.
For now this is not the primary concern:)
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.
Some small comments.
if (_maxSizeSingleEntry < newSize || | ||
_maxSize - std::min(_totalSizePinned, _maxSize) < newSize) { |
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.
This I don't understand/believe:
why not
sizeDiff = newSize - oldSize; // check for underflow...
if (totalSizePinnedPlusNonPinnedEverything + sizeDiff > _maxSize) erase(key);
```.
(+ The `_maxSizeSingleEntry` check of course, that one is undisputed.
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.
Because _maxSize
is of type MemorySize
which will throw an exception instead of becoming a negative size value. I remember fiddling around with this a lot until it worked and this is what my changes converged to. I must admit that I don't know anymore why I settled on these exact changes.
return; | ||
} | ||
if (masterState_ == MasterIteratorState::MASTER_STARTED && !isMaster) { | ||
conditionVariable_.wait(lock, [this, index]() { |
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.
I still think that the non-master approach + everybody having a timeout is better. We can probably dispute this further, the current state (forever blocking until the slow master times out) is a blocker for this PR.
|
Still WIP. Currently missing: