Skip to content
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

Add erase option to release cache #2180

Closed

Conversation

maysamyabandeh
Copy link
Contributor

@maysamyabandeh maysamyabandeh commented Apr 19, 2017

This is useful when we put the entries in the block cache for accounting
purposes and do not expect it to be used after it is released. If the cache does not
erase the item in such cases not only the performance of cache is
negatively affected but the item's destructor not being called at the
time of release might violate the assumptions about the lifetime of the
object.

The new change adds a force_erase option to the Release method and
returns a boolean to indicate whehter the item is successfully deleted.

This is useful when we put the entries in the block cache for accounting
purposes and do not expect it to be used later. If the cache does not
erase the item in such cases not only the performance of cache is
negatively affected but the item's destructor not being called at the
time of release might violate the assumptions about the lifetime of the
object.

The new change adds a force_erase option to the Release method and
returns a boolean to indicate whehter the item is successfully deleted.
if (!force_erase || erased) {
return erased;
} else {
return EraseAndConfirm(handle->key, handle->hash);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yiwu-arbug I think this implementation is correct. Feel free to suggest a more optimized version if you see it applies. Thanks

Copy link
Contributor

@yiwu-arbug yiwu-arbug Apr 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass context to EraseAndConfirm(), and call Cleanup(context) after that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would be the purpose of this change? Would it improve performance?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a bit cleaner.

@facebook-github-bot
Copy link
Contributor

@maysamyabandeh has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link
Contributor

@sagar0 sagar0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am curious, under what cases might one want to evict data immediately, instead of doing a lazy eviction.

Copy link
Contributor

@yiwu-arbug yiwu-arbug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a second thought I'm not sure if the force_erase flag will solve your problem. Say you erase the filter from cache before destructing a table, while something else holds a handle of the filter, the filter can still be destruct after the table has been destructed. Can you explain more how to get around it?

CleanupContext context;
CacheHandle* handle = reinterpret_cast<CacheHandle*>(h);
Unref(handle, true, &context);
Cleanup(context);
auto erased = context.to_delete_value.size() > 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update Unref() to return if item erased?

if (!force_erase || erased) {
return erased;
} else {
return EraseAndConfirm(handle->key, handle->hash);
Copy link
Contributor

@yiwu-arbug yiwu-arbug Apr 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass context to EraseAndConfirm(), and call Cleanup(context) after that.

// the cache is full
// The LRU list must be empty since the cache is full
assert(lru_.next == &lru_);
assert(!(usage_ > capacity_) || lru_.next == &lru_);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert(force_erase || lru_.next == &lru_) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be less strict that the current assert because even when force_erase it might be the case that usage_ > capacity_ and we do not want to skip lru_.next == &lru_ for that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

@maysamyabandeh
Copy link
Contributor Author

@yiwu-arbug Why would anybody else have a handle to the object that i) I have created, and ii) I am the only consumer? In the case of filters, if anybody else try to read the same filter, that is a bug. The return value of ::Release is meant to be used for this purpose, the releaser would assert that the object is not erroneously referenced by others.

@maysamyabandeh
Copy link
Contributor Author

@sagar0 The two use cases that I mentioned in the PR description are applicable. An example would be the partitioned filter of table that should be deleted before the table is closed.

@yiwu-arbug
Copy link
Contributor

@maysamyabandeh I see. I forget that the table is the only accessor of the filter.

@@ -637,6 +649,7 @@ void ClockCacheShard::Erase(const Slice& key, uint32_t hash) {
}
}
Cleanup(context);
return context.to_delete_value.size() > 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update UnsetInCache() to return if item erased?

@facebook-github-bot
Copy link
Contributor

@maysamyabandeh updated the pull request - view changes - changes since last import

@facebook-github-bot
Copy link
Contributor

@maysamyabandeh has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

Copy link
Contributor

@yiwu-arbug yiwu-arbug left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I forgot to accept it.

@maysamyabandeh
Copy link
Contributor Author

The failures in travis seems irrelevant:

db/db_compaction_test.cc:1269: Failure
Expected: (SizeAtLevel(i)) <= (target_size), actual: 43239165 vs 41943040
Run: org.rocksdb.WriteBatchThreadedTest testing now -> threadedWrites[WriteBatchThreadedTest(threadCount=50)] 
Assertion failed: (content_flags_.load(std::memory_order_relaxed) & (ContentFlags::DEFERRED | ContentFlags::HAS_PUT)), function Iterate, file db/write_batch.cc, line 385.

Moving on with landing...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants