Remove the unnecessary use of shared_ptr

Summary:
shared_ptr is slower than unique_ptr (which literally comes with no performance cost compare with raw pointers).
In memtable and memtable rep, we use shared_ptr when we'd actually should use unique_ptr.

According to igor's previous work, we are likely to make quite some performance gain from this diff.

Test Plan: make check

Reviewers: dhruba, igor, sdong, haobo

CC: leveldb

Differential Revision: https://reviews.facebook.net/D15213
main
kailiu 11 years ago
parent 787f11bb3b
commit eae1804f29
  1. 14
      db/memtable.cc
  2. 2
      db/memtable.h
  3. 24
      include/rocksdb/memtablerep.h
  4. 48
      util/hash_skiplist_rep.cc
  5. 4
      util/hash_skiplist_rep.h
  6. 8
      util/skiplistrep.cc
  7. 12
      util/vectorrep.cc

@ -85,11 +85,11 @@ class MemTableIterator: public Iterator {
MemTableIterator(MemTableRep* table, const ReadOptions& options) MemTableIterator(MemTableRep* table, const ReadOptions& options)
: iter_() { : iter_() {
if (options.prefix) { if (options.prefix) {
iter_ = table->GetPrefixIterator(*options.prefix); iter_.reset(table->GetPrefixIterator(*options.prefix));
} else if (options.prefix_seek) { } else if (options.prefix_seek) {
iter_ = table->GetDynamicPrefixIterator(); iter_.reset(table->GetDynamicPrefixIterator());
} else { } else {
iter_ = table->GetIterator(); iter_.reset(table->GetIterator());
} }
} }
@ -110,7 +110,7 @@ class MemTableIterator: public Iterator {
virtual Status status() const { return Status::OK(); } virtual Status status() const { return Status::OK(); }
private: private:
std::shared_ptr<MemTableRep::Iterator> iter_; std::unique_ptr<MemTableRep::Iterator> iter_;
std::string tmp_; // For passing to EncodeKey std::string tmp_; // For passing to EncodeKey
// No copying allowed // No copying allowed
@ -161,7 +161,7 @@ void MemTable::Add(SequenceNumber s, ValueType type,
bool MemTable::Get(const LookupKey& key, std::string* value, Status* s, bool MemTable::Get(const LookupKey& key, std::string* value, Status* s,
MergeContext& merge_context, const Options& options) { MergeContext& merge_context, const Options& options) {
Slice memkey = key.memtable_key(); Slice memkey = key.memtable_key();
std::shared_ptr<MemTableRep::Iterator> iter( std::unique_ptr<MemTableRep::Iterator> iter(
table_->GetIterator(key.user_key())); table_->GetIterator(key.user_key()));
iter->Seek(memkey.data()); iter->Seek(memkey.data());
@ -267,7 +267,7 @@ bool MemTable::Update(SequenceNumber seq, ValueType type,
LookupKey lkey(key, seq); LookupKey lkey(key, seq);
Slice memkey = lkey.memtable_key(); Slice memkey = lkey.memtable_key();
std::shared_ptr<MemTableRep::Iterator> iter( std::unique_ptr<MemTableRep::Iterator> iter(
table_->GetIterator(lkey.user_key())); table_->GetIterator(lkey.user_key()));
iter->Seek(memkey.data()); iter->Seek(memkey.data());
@ -329,7 +329,7 @@ size_t MemTable::CountSuccessiveMergeEntries(const LookupKey& key) {
// A total ordered iterator is costly for some memtablerep (prefix aware // A total ordered iterator is costly for some memtablerep (prefix aware
// reps). By passing in the user key, we allow efficient iterator creation. // reps). By passing in the user key, we allow efficient iterator creation.
// The iterator only needs to be ordered within the same user key. // The iterator only needs to be ordered within the same user key.
std::shared_ptr<MemTableRep::Iterator> iter( std::unique_ptr<MemTableRep::Iterator> iter(
table_->GetIterator(key.user_key())); table_->GetIterator(key.user_key()));
iter->Seek(memkey.data()); iter->Seek(memkey.data());

@ -143,7 +143,7 @@ class MemTable {
KeyComparator comparator_; KeyComparator comparator_;
int refs_; int refs_;
ArenaImpl arena_impl_; ArenaImpl arena_impl_;
shared_ptr<MemTableRep> table_; unique_ptr<MemTableRep> table_;
// These are used to manage memtable flushes to storage // These are used to manage memtable flushes to storage
bool flush_in_progress_; // started the flush bool flush_in_progress_; // started the flush

@ -111,27 +111,23 @@ class MemTableRep {
}; };
// Return an iterator over the keys in this representation. // Return an iterator over the keys in this representation.
virtual std::shared_ptr<Iterator> GetIterator() = 0; virtual Iterator* GetIterator() = 0;
// Return an iterator over at least the keys with the specified user key. The // Return an iterator over at least the keys with the specified user key. The
// iterator may also allow access to other keys, but doesn't have to. Default: // iterator may also allow access to other keys, but doesn't have to. Default:
// GetIterator(). // GetIterator().
virtual std::shared_ptr<Iterator> GetIterator(const Slice& user_key) { virtual Iterator* GetIterator(const Slice& user_key) { return GetIterator(); }
return GetIterator();
}
// Return an iterator over at least the keys with the specified prefix. The // Return an iterator over at least the keys with the specified prefix. The
// iterator may also allow access to other keys, but doesn't have to. Default: // iterator may also allow access to other keys, but doesn't have to. Default:
// GetIterator(). // GetIterator().
virtual std::shared_ptr<Iterator> GetPrefixIterator(const Slice& prefix) { virtual Iterator* GetPrefixIterator(const Slice& prefix) {
return GetIterator(); return GetIterator();
} }
// Return an iterator that has a special Seek semantics. The result of // Return an iterator that has a special Seek semantics. The result of
// a Seek might only include keys with the same prefix as the target key. // a Seek might only include keys with the same prefix as the target key.
virtual std::shared_ptr<Iterator> GetDynamicPrefixIterator() { virtual Iterator* GetDynamicPrefixIterator() { return GetIterator(); }
return GetIterator();
}
protected: protected:
// When *key is an internal key concatenated with the value, returns the // When *key is an internal key concatenated with the value, returns the
@ -144,8 +140,8 @@ class MemTableRep {
class MemTableRepFactory { class MemTableRepFactory {
public: public:
virtual ~MemTableRepFactory() { }; virtual ~MemTableRepFactory() { };
virtual std::shared_ptr<MemTableRep> CreateMemTableRep( virtual MemTableRep* CreateMemTableRep(MemTableRep::KeyComparator&,
MemTableRep::KeyComparator&, Arena*) = 0; Arena*) = 0;
virtual const char* Name() const = 0; virtual const char* Name() const = 0;
}; };
@ -161,8 +157,8 @@ class VectorRepFactory : public MemTableRepFactory {
const size_t count_; const size_t count_;
public: public:
explicit VectorRepFactory(size_t count = 0) : count_(count) { } explicit VectorRepFactory(size_t count = 0) : count_(count) { }
virtual std::shared_ptr<MemTableRep> CreateMemTableRep( virtual MemTableRep* CreateMemTableRep(MemTableRep::KeyComparator&,
MemTableRep::KeyComparator&, Arena*) override; Arena*) override;
virtual const char* Name() const override { virtual const char* Name() const override {
return "VectorRepFactory"; return "VectorRepFactory";
} }
@ -171,8 +167,8 @@ public:
// This uses a skip list to store keys. It is the default. // This uses a skip list to store keys. It is the default.
class SkipListFactory : public MemTableRepFactory { class SkipListFactory : public MemTableRepFactory {
public: public:
virtual std::shared_ptr<MemTableRep> CreateMemTableRep( virtual MemTableRep* CreateMemTableRep(MemTableRep::KeyComparator&,
MemTableRep::KeyComparator&, Arena*) override; Arena*) override;
virtual const char* Name() const override { virtual const char* Name() const override {
return "SkipListFactory"; return "SkipListFactory";
} }

@ -31,17 +31,15 @@ class HashSkipListRep : public MemTableRep {
virtual ~HashSkipListRep(); virtual ~HashSkipListRep();
virtual std::shared_ptr<MemTableRep::Iterator> GetIterator() override; virtual MemTableRep::Iterator* GetIterator() override;
virtual std::shared_ptr<MemTableRep::Iterator> GetIterator( virtual MemTableRep::Iterator* GetIterator(const Slice& slice) override;
const Slice& slice) override;
virtual std::shared_ptr<MemTableRep::Iterator> GetPrefixIterator( virtual MemTableRep::Iterator* GetPrefixIterator(const Slice& prefix)
const Slice& prefix) override;
virtual std::shared_ptr<MemTableRep::Iterator> GetDynamicPrefixIterator()
override; override;
virtual MemTableRep::Iterator* GetDynamicPrefixIterator() override;
private: private:
friend class DynamicIterator; friend class DynamicIterator;
typedef SkipList<const char*, MemTableRep::KeyComparator&> Bucket; typedef SkipList<const char*, MemTableRep::KeyComparator&> Bucket;
@ -208,18 +206,15 @@ class HashSkipListRep : public MemTableRep {
virtual void SeekToLast() { } virtual void SeekToLast() { }
private: private:
}; };
std::shared_ptr<EmptyIterator> empty_iterator_;
}; };
HashSkipListRep::HashSkipListRep(MemTableRep::KeyComparator& compare, HashSkipListRep::HashSkipListRep(MemTableRep::KeyComparator& compare,
Arena* arena, const SliceTransform* transform, size_t bucket_size) Arena* arena, const SliceTransform* transform,
size_t bucket_size)
: bucket_size_(bucket_size), : bucket_size_(bucket_size),
transform_(transform), transform_(transform),
compare_(compare), compare_(compare),
arena_(arena), arena_(arena) {
empty_iterator_(std::make_shared<EmptyIterator>()) {
buckets_ = new port::AtomicPointer[bucket_size]; buckets_ = new port::AtomicPointer[bucket_size];
for (size_t i = 0; i < bucket_size_; ++i) { for (size_t i = 0; i < bucket_size_; ++i) {
@ -263,7 +258,7 @@ size_t HashSkipListRep::ApproximateMemoryUsage() {
return sizeof(buckets_); return sizeof(buckets_);
} }
std::shared_ptr<MemTableRep::Iterator> HashSkipListRep::GetIterator() { MemTableRep::Iterator* HashSkipListRep::GetIterator() {
auto list = new Bucket(compare_, arena_); auto list = new Bucket(compare_, arena_);
for (size_t i = 0; i < bucket_size_; ++i) { for (size_t i = 0; i < bucket_size_; ++i) {
auto bucket = GetBucket(i); auto bucket = GetBucket(i);
@ -274,35 +269,30 @@ std::shared_ptr<MemTableRep::Iterator> HashSkipListRep::GetIterator() {
} }
} }
} }
return std::make_shared<Iterator>(list); return new Iterator(list);
} }
std::shared_ptr<MemTableRep::Iterator> HashSkipListRep::GetPrefixIterator( MemTableRep::Iterator* HashSkipListRep::GetPrefixIterator(const Slice& prefix) {
const Slice& prefix) {
auto bucket = GetBucket(prefix); auto bucket = GetBucket(prefix);
if (bucket == nullptr) { if (bucket == nullptr) {
return empty_iterator_; return new EmptyIterator();
} }
return std::make_shared<Iterator>(bucket, false); return new Iterator(bucket, false);
} }
std::shared_ptr<MemTableRep::Iterator> HashSkipListRep::GetIterator( MemTableRep::Iterator* HashSkipListRep::GetIterator(const Slice& slice) {
const Slice& slice) {
return GetPrefixIterator(transform_->Transform(slice)); return GetPrefixIterator(transform_->Transform(slice));
} }
std::shared_ptr<MemTableRep::Iterator> MemTableRep::Iterator* HashSkipListRep::GetDynamicPrefixIterator() {
HashSkipListRep::GetDynamicPrefixIterator() { return new DynamicIterator(*this);
return std::make_shared<DynamicIterator>(*this);
} }
} // anon namespace } // anon namespace
std::shared_ptr<MemTableRep> MemTableRep* HashSkipListRepFactory::CreateMemTableRep(
HashSkipListRepFactory::CreateMemTableRep(MemTableRep::KeyComparator &compare, MemTableRep::KeyComparator& compare, Arena* arena) {
Arena *arena) { return new HashSkipListRep(compare, arena, transform_, bucket_count_);
return std::make_shared<HashSkipListRep>(compare, arena, transform_,
bucket_count_);
} }
MemTableRepFactory* NewHashSkipListRepFactory( MemTableRepFactory* NewHashSkipListRepFactory(

@ -21,8 +21,8 @@ class HashSkipListRepFactory : public MemTableRepFactory {
virtual ~HashSkipListRepFactory() { delete transform_; } virtual ~HashSkipListRepFactory() { delete transform_; }
virtual std::shared_ptr<MemTableRep> CreateMemTableRep( virtual MemTableRep* CreateMemTableRep(MemTableRep::KeyComparator& compare,
MemTableRep::KeyComparator& compare, Arena* arena) override; Arena* arena) override;
virtual const char* Name() const override { virtual const char* Name() const override {
return "HashSkipListRepFactory"; return "HashSkipListRepFactory";

@ -90,15 +90,15 @@ public:
// Unhide default implementations of GetIterator // Unhide default implementations of GetIterator
using MemTableRep::GetIterator; using MemTableRep::GetIterator;
virtual std::shared_ptr<MemTableRep::Iterator> GetIterator() override { virtual MemTableRep::Iterator* GetIterator() override {
return std::make_shared<SkipListRep::Iterator>(&skip_list_); return new SkipListRep::Iterator(&skip_list_);
} }
}; };
} }
std::shared_ptr<MemTableRep> SkipListFactory::CreateMemTableRep ( MemTableRep* SkipListFactory::CreateMemTableRep(
MemTableRep::KeyComparator& compare, Arena* arena) { MemTableRep::KeyComparator& compare, Arena* arena) {
return std::shared_ptr<MemTableRep>(new SkipListRep(compare, arena)); return new SkipListRep(compare, arena);
} }
} // namespace rocksdb } // namespace rocksdb

@ -88,7 +88,7 @@ class VectorRep : public MemTableRep {
using MemTableRep::GetIterator; using MemTableRep::GetIterator;
// Return an iterator over the keys in this representation. // Return an iterator over the keys in this representation.
virtual std::shared_ptr<MemTableRep::Iterator> GetIterator() override; virtual MemTableRep::Iterator* GetIterator() override;
private: private:
friend class Iterator; friend class Iterator;
@ -228,22 +228,22 @@ void VectorRep::Iterator::SeekToLast() {
} }
} }
std::shared_ptr<MemTableRep::Iterator> VectorRep::GetIterator() { MemTableRep::Iterator* VectorRep::GetIterator() {
ReadLock l(&rwlock_); ReadLock l(&rwlock_);
// Do not sort here. The sorting would be done the first time // Do not sort here. The sorting would be done the first time
// a Seek is performed on the iterator. // a Seek is performed on the iterator.
if (immutable_) { if (immutable_) {
return std::make_shared<Iterator>(this, bucket_, compare_); return new Iterator(this, bucket_, compare_);
} else { } else {
std::shared_ptr<Bucket> tmp; std::shared_ptr<Bucket> tmp;
tmp.reset(new Bucket(*bucket_)); // make a copy tmp.reset(new Bucket(*bucket_)); // make a copy
return std::make_shared<Iterator>(nullptr, tmp, compare_); return new Iterator(nullptr, tmp, compare_);
} }
} }
} // anon namespace } // anon namespace
std::shared_ptr<MemTableRep> VectorRepFactory::CreateMemTableRep( MemTableRep* VectorRepFactory::CreateMemTableRep(
MemTableRep::KeyComparator& compare, Arena* arena) { MemTableRep::KeyComparator& compare, Arena* arena) {
return std::make_shared<VectorRep>(compare, arena, count_); return new VectorRep(compare, arena, count_);
} }
} // namespace rocksdb } // namespace rocksdb

Loading…
Cancel
Save