mirror of
https://github.com/facebook/rocksdb.git
synced 2024-11-27 11:43:49 +00:00
b52620ab0e
Summary: cache_bench wasn't generating 16B keys, which are necessary for FastLRUCache. Also: - Added asserts in cache_bench, which is assuming that inserts never fail. When they fail (for example, if we used keys of the wrong size), memory allocated to the values will becomes leaked, and eventually the program crashes. - Move kCacheKeySize to the right spot. Pull Request resolved: https://github.com/facebook/rocksdb/pull/10234 Test Plan: ``make -j24 check``. Also, run cache_bench with FastLRUCache and check that memory usage doesn't blow up: ``./cache_bench -cache_type=fast_lru_cache -num_shard_bits=6 -skewed=true \ -lookup_insert_percent=100 -lookup_percent=0 -insert_percent=0 -erase_percent=0 \ -populate_cache=true -cache_size=1073741824 -ops_per_thread=10000000 \ -value_bytes=8192 -resident_ratio=1 -threads=16`` Reviewed By: pdillinger Differential Revision: D37382949 Pulled By: guidotag fbshipit-source-id: b697a942ebb215de5d341f98dc8566763436ba9b
135 lines
5.3 KiB
C++
135 lines
5.3 KiB
C++
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
|
// This source code is licensed under both the GPLv2 (found in the
|
|
// COPYING file in the root directory) and Apache 2.0 License
|
|
// (found in the LICENSE.Apache file in the root directory).
|
|
|
|
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
#include "rocksdb/rocksdb_namespace.h"
|
|
#include "rocksdb/slice.h"
|
|
|
|
namespace ROCKSDB_NAMESPACE {
|
|
|
|
class Cache;
|
|
|
|
// A standard holder for fixed-size block cache keys (and for related caches).
|
|
// They are created through one of these, each using its own range of values:
|
|
// * CacheKey::CreateUniqueForCacheLifetime
|
|
// * CacheKey::CreateUniqueForProcessLifetime
|
|
// * Default ctor ("empty" cache key)
|
|
// * OffsetableCacheKey->WithOffset
|
|
//
|
|
// The first two use atomic counters to guarantee uniqueness over the given
|
|
// lifetime and the last uses a form of universally unique identifier for
|
|
// uniqueness with very high probabilty (and guaranteed for files generated
|
|
// during a single process lifetime).
|
|
//
|
|
// CacheKeys are currently used by calling AsSlice() to pass as a key to
|
|
// Cache. For performance, the keys are endianness-dependent (though otherwise
|
|
// portable). (Persistable cache entries are not intended to cross platforms.)
|
|
class CacheKey {
|
|
public:
|
|
// For convenience, constructs an "empty" cache key that is never returned
|
|
// by other means.
|
|
inline CacheKey() : session_etc64_(), offset_etc64_() {}
|
|
|
|
inline bool IsEmpty() const {
|
|
return (session_etc64_ == 0) & (offset_etc64_ == 0);
|
|
}
|
|
|
|
// Use this cache key as a Slice (byte order is endianness-dependent)
|
|
inline Slice AsSlice() const {
|
|
static_assert(sizeof(*this) == 16, "Standardized on 16-byte cache key");
|
|
assert(!IsEmpty());
|
|
return Slice(reinterpret_cast<const char *>(this), sizeof(*this));
|
|
}
|
|
|
|
// Create a CacheKey that is unique among others associated with this Cache
|
|
// instance. Depends on Cache::NewId. This is useful for block cache
|
|
// "reservations".
|
|
static CacheKey CreateUniqueForCacheLifetime(Cache *cache);
|
|
|
|
// Create a CacheKey that is unique among others for the lifetime of this
|
|
// process. This is useful for saving in a static data member so that
|
|
// different DB instances can agree on a cache key for shared entities,
|
|
// such as for CacheEntryStatsCollector.
|
|
static CacheKey CreateUniqueForProcessLifetime();
|
|
|
|
protected:
|
|
friend class OffsetableCacheKey;
|
|
CacheKey(uint64_t session_etc64, uint64_t offset_etc64)
|
|
: session_etc64_(session_etc64), offset_etc64_(offset_etc64) {}
|
|
uint64_t session_etc64_;
|
|
uint64_t offset_etc64_;
|
|
};
|
|
|
|
constexpr uint8_t kCacheKeySize = static_cast<uint8_t>(sizeof(CacheKey));
|
|
|
|
// A file-specific generator of cache keys, sometimes referred to as the
|
|
// "base" cache key for a file because all the cache keys for various offsets
|
|
// within the file are computed using simple arithmetic. The basis for the
|
|
// general approach is dicussed here: https://github.com/pdillinger/unique_id
|
|
// Heavily related to GetUniqueIdFromTableProperties.
|
|
//
|
|
// If the db_id, db_session_id, and file_number come from the file's table
|
|
// properties, then the keys will be stable across DB::Open/Close, backup/
|
|
// restore, import/export, etc.
|
|
//
|
|
// This class "is a" CacheKey only privately so that it is not misused as
|
|
// a ready-to-use CacheKey.
|
|
class OffsetableCacheKey : private CacheKey {
|
|
public:
|
|
// For convenience, constructs an "empty" cache key that should not be used.
|
|
inline OffsetableCacheKey() : CacheKey() {}
|
|
|
|
// Constructs an OffsetableCacheKey with the given information about a file.
|
|
// max_offset is based on file size (see WithOffset) and is required here to
|
|
// choose an appropriate (sub-)encoding. This constructor never generates an
|
|
// "empty" base key.
|
|
OffsetableCacheKey(const std::string &db_id, const std::string &db_session_id,
|
|
uint64_t file_number, uint64_t max_offset);
|
|
|
|
inline bool IsEmpty() const {
|
|
bool result = session_etc64_ == 0;
|
|
assert(!(offset_etc64_ > 0 && result));
|
|
return result;
|
|
}
|
|
|
|
// Construct a CacheKey for an offset within a file, which must be
|
|
// <= max_offset provided in constructor. An offset is not necessarily a
|
|
// byte offset if a smaller unique identifier of keyable offsets is used.
|
|
//
|
|
// This class was designed to make this hot code extremely fast.
|
|
inline CacheKey WithOffset(uint64_t offset) const {
|
|
assert(!IsEmpty());
|
|
assert(offset <= max_offset_);
|
|
return CacheKey(session_etc64_, offset_etc64_ ^ offset);
|
|
}
|
|
|
|
// The "common prefix" is a shared prefix for all the returned CacheKeys,
|
|
// that also happens to usually be the same among many files in the same DB,
|
|
// so is efficient and highly accurate (not perfectly) for DB-specific cache
|
|
// dump selection (but not file-specific).
|
|
static constexpr size_t kCommonPrefixSize = 8;
|
|
inline Slice CommonPrefixSlice() const {
|
|
static_assert(sizeof(session_etc64_) == kCommonPrefixSize,
|
|
"8 byte common prefix expected");
|
|
assert(!IsEmpty());
|
|
assert(&this->session_etc64_ == static_cast<const void *>(this));
|
|
|
|
return Slice(reinterpret_cast<const char *>(this), kCommonPrefixSize);
|
|
}
|
|
|
|
// For any max_offset <= this value, the same encoding scheme is guaranteed.
|
|
static constexpr uint64_t kMaxOffsetStandardEncoding = 0xffffffffffU;
|
|
|
|
private:
|
|
#ifndef NDEBUG
|
|
uint64_t max_offset_ = 0;
|
|
#endif
|
|
};
|
|
|
|
} // namespace ROCKSDB_NAMESPACE
|