From 3b35134e4b46f16f46e0a96424d29ecf4e43559c Mon Sep 17 00:00:00 2001 From: Andrew Kryczka Date: Thu, 26 Jan 2017 11:18:19 -0800 Subject: [PATCH] Avoid cache lookups for range deletion meta-block Summary: I added the Cache::Ref() function a couple weeks ago (#1761) to make this feature possible. Like other meta-blocks, rep_->range_del_entry holds a cache handle to pin the range deletion block in uncompressed block cache for the duration of the table reader's lifetime. We can reuse this cache handle to create an iterator over this meta-block without any cache lookup. Ref() is used to increment the cache handle's refcount in case the returned iterator outlives the table reader. Closes https://github.com/facebook/rocksdb/pull/1801 Differential Revision: D4458782 Pulled By: ajkr fbshipit-source-id: 2883f10 --- table/block_based_table_reader.cc | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/table/block_based_table_reader.cc b/table/block_based_table_reader.cc index f85d570b8..b106623eb 100644 --- a/table/block_based_table_reader.cc +++ b/table/block_based_table_reader.cc @@ -1489,13 +1489,30 @@ InternalIterator* BlockBasedTable::NewIterator(const ReadOptions& read_options, InternalIterator* BlockBasedTable::NewRangeTombstoneIterator( const ReadOptions& read_options) { if (rep_->range_del_handle.IsNull()) { + // The block didn't exist, nullptr indicates no range tombstones. return nullptr; } + if (rep_->range_del_entry.cache_handle != nullptr) { + // We have a handle to an uncompressed block cache entry that's held for + // this table's lifetime. Increment its refcount before returning an + // iterator based on it since the returned iterator may outlive this table + // reader. + assert(rep_->range_del_entry.value != nullptr); + Cache* block_cache = rep_->table_options.block_cache.get(); + assert(block_cache != nullptr); + if (block_cache->Ref(rep_->range_del_entry.cache_handle)) { + auto iter = rep_->range_del_entry.value->NewIterator( + &rep_->internal_comparator, nullptr /* iter */, + true /* total_order_seek */, rep_->ioptions.statistics); + iter->RegisterCleanup(&ReleaseCachedEntry, block_cache, + rep_->range_del_entry.cache_handle); + return iter; + } + } std::string str; rep_->range_del_handle.EncodeTo(&str); - // Even though range_del_entry already references the meta-block when block - // cache is enabled, we still call the below function to get another reference - // since the caller may need the iterator beyond this table reader's lifetime. + // The meta-block exists but isn't in uncompressed block cache (maybe because + // it is disabled), so go through the full lookup process. return NewDataBlockIterator(rep_, read_options, Slice(str)); }