Summary: Currently the point lookup values are copied to a string provided by the user. This incures an extra memcpy cost. This patch allows doing point lookup via a PinnableSlice which pins the source memory location (instead of copying their content) and releases them after the content is consumed by the user. The old API of Get(string) is translated to the new API underneath. Here is the summary for improvements: 1. value 100 byte: 1.8% regular, 1.2% merge values 2. value 1k byte: 11.5% regular, 7.5% merge values 3. value 10k byte: 26% regular, 29.9% merge values The improvement for merge could be more if we extend this approach to pin the merge output and delay the full merge operation until the user actually needs it. We have put that for future work. PS: Sometimes we observe a small decrease in performance when switching from t5452014 to this patch but with the old Get(string) API. The difference is a little and could be noise. More importantly it is safely cancelled Closes https://github.com/facebook/rocksdb/pull/1732 Differential Revision: D4374613 Pulled By: maysamyabandeh fbshipit-source-id: a077f1amain
parent
e04480faed
commit
54d94e9c2c
@ -0,0 +1,73 @@ |
||||
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||
//
|
||||
// An iterator yields a sequence of key/value pairs from a source.
|
||||
// The following class defines the interface. Multiple implementations
|
||||
// are provided by this library. In particular, iterators are provided
|
||||
// to access the contents of a Table or a DB.
|
||||
//
|
||||
// Multiple threads can invoke const methods on an Iterator without
|
||||
// external synchronization, but if any of the threads may call a
|
||||
// non-const method, all threads accessing the same Iterator must use
|
||||
// external synchronization.
|
||||
|
||||
#ifndef INCLUDE_ROCKSDB_CLEANABLE_H_ |
||||
#define INCLUDE_ROCKSDB_CLEANABLE_H_ |
||||
|
||||
namespace rocksdb { |
||||
|
||||
class Cleanable { |
||||
public: |
||||
Cleanable(); |
||||
~Cleanable(); |
||||
// Clients are allowed to register function/arg1/arg2 triples that
|
||||
// will be invoked when this iterator is destroyed.
|
||||
//
|
||||
// Note that unlike all of the preceding methods, this method is
|
||||
// not abstract and therefore clients should not override it.
|
||||
typedef void (*CleanupFunction)(void* arg1, void* arg2); |
||||
void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); |
||||
void DelegateCleanupsTo(Cleanable* other); |
||||
// DoCkeanup and also resets the pointers for reuse
|
||||
inline void Reset() { |
||||
DoCleanup(); |
||||
cleanup_.function = nullptr; |
||||
cleanup_.next = nullptr; |
||||
} |
||||
|
||||
protected: |
||||
struct Cleanup { |
||||
CleanupFunction function; |
||||
void* arg1; |
||||
void* arg2; |
||||
Cleanup* next; |
||||
}; |
||||
Cleanup cleanup_; |
||||
// It also becomes the owner of c
|
||||
void RegisterCleanup(Cleanup* c); |
||||
|
||||
private: |
||||
// Performs all the cleanups. It does not reset the pointers. Making it
|
||||
// private
|
||||
// to prevent misuse
|
||||
inline void DoCleanup() { |
||||
if (cleanup_.function != nullptr) { |
||||
(*cleanup_.function)(cleanup_.arg1, cleanup_.arg2); |
||||
for (Cleanup* c = cleanup_.next; c != nullptr;) { |
||||
(*c->function)(c->arg1, c->arg2); |
||||
Cleanup* next = c->next; |
||||
delete c; |
||||
c = next; |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
|
||||
} // namespace rocksdb
|
||||
|
||||
#endif // INCLUDE_ROCKSDB_CLEANABLE_H_
|
Loading…
Reference in new issue