Unverified Commit 1eb7b8cc authored by Connor's avatar Connor Committed by GitHub

Add `NumBlobFilesAtLevel` property (#132)

* titan level blob file count
Signed-off-by: 's avatarConnor1996 <zbk602423539@gmail.com>
parent aea29d31
......@@ -145,6 +145,10 @@ class TitanDB : public StackableDB {
virtual TitanDBOptions GetTitanDBOptions() const = 0;
struct Properties {
// "rocksdb.titandb.num-blob-files-at-level<N>" - returns string containing
// the number of blob files at level <N>, where <N> is an ASCII
// representation of a level number (e.g., "0")."
static const std::string kNumBlobFilesAtLevelPrefix;
// "rocksdb.titandb.live-blob-size" - returns total blob value size
// referenced by LSM tree.
static const std::string kLiveBlobSize;
......@@ -159,19 +163,19 @@ class TitanDB : public StackableDB {
// blob files.
static const std::string kObsoleteBlobFileSize;
// "rocksdb.titandb.discardable_ratio_le0_file_num" - returns count of
// file whose discardable ratio is less or equal to 0%.
// file whose discardable ratio is less or equal to 0%.
static const std::string kNumDiscardableRatioLE0File;
// "rocksdb.titandb.discardable_ratio_le20_file_num" - returns count of
// file whose discardable ratio is less or equal to 20%.
// file whose discardable ratio is less or equal to 20%.
static const std::string kNumDiscardableRatioLE20File;
// "rocksdb.titandb.discardable_ratio_le50_file_num" - returns count of
// file whose discardable ratio is less or equal to 50%.
// file whose discardable ratio is less or equal to 50%.
static const std::string kNumDiscardableRatioLE50File;
// "rocksdb.titandb.discardable_ratio_le80_file_num" - returns count of
// file whose discardable ratio is less or equal to 80%.
// file whose discardable ratio is less or equal to 80%.
static const std::string kNumDiscardableRatioLE80File;
// "rocksdb.titandb.discardable_ratio_le100_file_num" - returns count of
// file whose discardable ratio is less or equal to 100%.
// file whose discardable ratio is less or equal to 100%.
static const std::string kNumDiscardableRatioLE100File;
};
......
......@@ -230,6 +230,9 @@ void BlobFileSet::AddColumnFamilies(
file_cache_, stats_);
auto blob_storage = std::make_shared<BlobStorage>(
db_options_, cf.second, cf.first, file_cache, stats_);
if (stats_ != nullptr) {
stats_->InitializeCF(cf.first, blob_storage);
}
column_families_.emplace(cf.first, blob_storage);
}
}
......
......@@ -278,7 +278,7 @@ void BlobFileMeta::FileStateTransit(const FileEvent& event) {
TitanInternalStats::StatsType BlobFileMeta::GetDiscardableRatioLevel() const {
auto ratio = GetDiscardableRatio();
TitanInternalStats::StatsType type;
if (ratio == 0) {
if (ratio < std::numeric_limits<double>::epsilon()) {
type = TitanInternalStats::NUM_DISCARDABLE_RATIO_LE0;
} else if (ratio <= 0.2) {
type = TitanInternalStats::NUM_DISCARDABLE_RATIO_LE20;
......
......@@ -90,6 +90,7 @@ void BlobStorage::AddBlobFile(std::shared_ptr<BlobFileMeta>& file) {
MutexLock l(&mutex_);
files_.emplace(std::make_pair(file->file_number(), file));
blob_ranges_.emplace(std::make_pair(Slice(file->smallest_key()), file));
levels_file_count_[file->file_level()]++;
AddStats(stats_, cf_id_, file->GetDiscardableRatioLevel(), 1);
AddStats(stats_, cf_id_, TitanInternalStats::LIVE_BLOB_FILE_SIZE,
file->file_size());
......@@ -114,6 +115,7 @@ void BlobStorage::MarkFileObsoleteLocked(std::shared_ptr<BlobFileMeta> file,
obsolete_files_.push_back(
std::make_pair(file->file_number(), obsolete_sequence));
file->FileStateTransit(BlobFileMeta::FileEvent::kDelete);
levels_file_count_[file->file_level()]--;
SubStats(stats_, cf_id_, file->GetDiscardableRatioLevel(), 1);
SubStats(stats_, cf_id_, TitanInternalStats::LIVE_BLOB_SIZE,
file->live_data_size());
......
......@@ -31,6 +31,7 @@ class BlobStorage {
: db_options_(_db_options),
cf_options_(_cf_options),
cf_id_(cf_id),
levels_file_count_(_cf_options.num_levels, 0),
blob_ranges_(InternalComparator(_cf_options.comparator)),
file_cache_(_file_cache),
destroyed_(false),
......@@ -113,6 +114,14 @@ class BlobStorage {
return files_.size();
}
int NumBlobFilesAtLevel(int level) const {
MutexLock l(&mutex_);
if (level >= static_cast<int>(levels_file_count_.size())) {
return 0;
}
return levels_file_count_[level];
}
// Returns the number of obsolete blob files.
// TODO: use this method to calculate `kNumObsoleteBlobFile` DB property.
std::size_t NumObsoleteBlobFiles() const {
......@@ -142,7 +151,9 @@ class BlobStorage {
mutable port::Mutex mutex_;
// Only BlobStorage OWNS BlobFileMeta
// file_number -> file_meta
std::unordered_map<uint64_t, std::shared_ptr<BlobFileMeta>> files_;
std::vector<int> levels_file_count_;
class InternalComparator {
public:
......
......@@ -304,10 +304,6 @@ Status TitanDBImpl::OpenImpl(const std::vector<TitanCFDescriptor>& descs,
cf_with_compaction.push_back((*handles)[i]);
}
}
// Initialize Titan internals.
if (stats_ != nullptr) {
stats_->Initialize(column_families);
}
s = blob_file_set_->Open(column_families);
if (!s.ok()) {
return s;
......
#include "titan_stats.h"
#include "titan/db.h"
#include "blob_file_set.h"
#include "blob_storage.h"
#include "monitoring/statistics_impl.h"
#include <functional>
#include <map>
#include <string>
......@@ -16,6 +19,8 @@ std::shared_ptr<Statistics> CreateDBStatistics() {
static const std::string titandb_prefix = "rocksdb.titandb.";
static const std::string num_blob_files_at_level_prefix =
"num-blob-files-at-level";
static const std::string live_blob_size = "live-blob-size";
static const std::string num_live_blob_file = "num-live-blob-file";
static const std::string num_obsolete_blob_file = "num-obsolete-blob-file";
......@@ -32,6 +37,8 @@ static const std::string num_discardable_ratio_le80_file =
static const std::string num_discardable_ratio_le100_file =
"num-discardable-ratio-le100-file";
const std::string TitanDB::Properties::kNumBlobFilesAtLevelPrefix =
titandb_prefix + num_blob_files_at_level_prefix;
const std::string TitanDB::Properties::kLiveBlobSize =
titandb_prefix + live_blob_size;
const std::string TitanDB::Properties::kNumLiveBlobFile =
......@@ -53,28 +60,50 @@ const std::string TitanDB::Properties::kNumDiscardableRatioLE80File =
const std::string TitanDB::Properties::kNumDiscardableRatioLE100File =
titandb_prefix + num_discardable_ratio_le100_file;
const std::unordered_map<std::string, TitanInternalStats::StatsType>
const std::unordered_map<
std::string, std::function<uint64_t(const TitanInternalStats*, Slice)>>
TitanInternalStats::stats_type_string_map = {
{TitanDB::Properties::kNumBlobFilesAtLevelPrefix,
&TitanInternalStats::HandleNumBlobFilesAtLevel},
{TitanDB::Properties::kLiveBlobSize,
TitanInternalStats::LIVE_BLOB_SIZE},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::LIVE_BLOB_SIZE, std::placeholders::_2)},
{TitanDB::Properties::kNumLiveBlobFile,
TitanInternalStats::NUM_LIVE_BLOB_FILE},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::NUM_LIVE_BLOB_FILE,
std::placeholders::_2)},
{TitanDB::Properties::kNumObsoleteBlobFile,
TitanInternalStats::NUM_OBSOLETE_BLOB_FILE},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::NUM_OBSOLETE_BLOB_FILE,
std::placeholders::_2)},
{TitanDB::Properties::kLiveBlobFileSize,
TitanInternalStats::LIVE_BLOB_FILE_SIZE},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::LIVE_BLOB_FILE_SIZE,
std::placeholders::_2)},
{TitanDB::Properties::kObsoleteBlobFileSize,
TitanInternalStats::OBSOLETE_BLOB_FILE_SIZE},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::OBSOLETE_BLOB_FILE_SIZE,
std::placeholders::_2)},
{TitanDB::Properties::kNumDiscardableRatioLE0File,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE0},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE0,
std::placeholders::_2)},
{TitanDB::Properties::kNumDiscardableRatioLE20File,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE20},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE20,
std::placeholders::_2)},
{TitanDB::Properties::kNumDiscardableRatioLE50File,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE50},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE50,
std::placeholders::_2)},
{TitanDB::Properties::kNumDiscardableRatioLE80File,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE80},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE80,
std::placeholders::_2)},
{TitanDB::Properties::kNumDiscardableRatioLE100File,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE100},
std::bind(&TitanInternalStats::HandleStatsValue, std::placeholders::_1,
TitanInternalStats::NUM_DISCARDABLE_RATIO_LE100,
std::placeholders::_2)},
};
const std::array<std::string,
......@@ -85,6 +114,52 @@ const std::array<std::string,
"GC ",
}};
// Assumes that trailing numbers represent an optional argument. This requires
// property names to not end with numbers.
std::pair<Slice, Slice> GetPropertyNameAndArg(const Slice& property) {
Slice name = property, arg = property;
size_t sfx_len = 0;
while (sfx_len < property.size() &&
isdigit(property[property.size() - sfx_len - 1])) {
++sfx_len;
}
name.remove_suffix(sfx_len);
arg.remove_prefix(property.size() - sfx_len);
return {name, arg};
}
bool TitanInternalStats::GetIntProperty(const Slice& property,
uint64_t* value) const {
auto ppt = GetPropertyNameAndArg(property);
auto p = stats_type_string_map.find(ppt.first.ToString());
if (p != stats_type_string_map.end()) {
*value = (p->second)(this, ppt.second);
return true;
}
return false;
}
bool TitanInternalStats::GetStringProperty(const Slice& property,
std::string* value) const {
uint64_t int_value;
if (GetIntProperty(property, &int_value)) {
*value = std::to_string(int_value);
return true;
}
return false;
}
uint64_t TitanInternalStats::HandleStatsValue(
TitanInternalStats::StatsType type, Slice _arg) const {
return stats_[type].load(std::memory_order_relaxed);
}
uint64_t TitanInternalStats::HandleNumBlobFilesAtLevel(Slice arg) const {
auto s = arg.ToString();
int level = ParseInt(s);
return blob_storage_->NumBlobFilesAtLevel(level);
}
void TitanInternalStats::DumpAndResetInternalOpStats(LogBuffer* log_buffer) {
constexpr double GB = 1.0 * 1024 * 1024 * 1024;
constexpr double SECOND = 1.0 * 1000000;
......@@ -130,5 +205,10 @@ void TitanInternalStats::DumpAndResetInternalOpStats(LogBuffer* log_buffer) {
}
}
void TitanStats::InitializeCF(uint32_t cf_id,
std::shared_ptr<BlobStorage> blob_storage) {
internal_stats_[cf_id] = std::make_shared<TitanInternalStats>(blob_storage);
}
} // namespace titandb
} // namespace rocksdb
......@@ -13,6 +13,7 @@
#include "rocksdb/statistics.h"
#include "titan/options.h"
#include "titan/statistics.h"
#include "util/string_util.h"
namespace rocksdb {
namespace titandb {
......@@ -46,6 +47,8 @@ using InternalOpStats =
static_cast<size_t>(
InternalOpStatsType::INTERNAL_OP_STATS_ENUM_MAX)>;
class BlobStorage;
// Titan internal stats does NOT optimize race
// condition by making thread local copies of
// data.
......@@ -67,7 +70,10 @@ class TitanInternalStats {
INTERNAL_STATS_ENUM_MAX,
};
TitanInternalStats() { Clear(); }
TitanInternalStats(std::shared_ptr<BlobStorage> blob_storage)
: blob_storage_(blob_storage) {
Clear();
}
void Clear() {
for (int stat = 0; stat < INTERNAL_STATS_ENUM_MAX; stat++) {
......@@ -101,32 +107,21 @@ class TitanInternalStats {
v.fetch_sub(value, std::memory_order_relaxed);
}
bool GetIntProperty(const Slice& property, uint64_t* value) const {
auto p = stats_type_string_map.find(property.ToString());
if (p != stats_type_string_map.end()) {
*value = stats_[p->second].load(std::memory_order_relaxed);
return true;
}
return false;
}
bool GetStringProperty(const Slice& property, std::string* value) const {
uint64_t int_value;
if (GetIntProperty(property, &int_value)) {
*value = std::to_string(int_value);
return true;
}
return false;
}
InternalOpStats* GetInternalOpStatsForType(InternalOpType type) {
return &internal_op_stats_[static_cast<int>(type)];
}
void DumpAndResetInternalOpStats(LogBuffer* log_buffer);
bool GetIntProperty(const Slice& property, uint64_t* value) const;
bool GetStringProperty(const Slice& property, std::string* value) const;
uint64_t HandleStatsValue(TitanInternalStats::StatsType type,
Slice _arg) const;
uint64_t HandleNumBlobFilesAtLevel(Slice arg) const;
private:
static const std::unordered_map<std::string, TitanInternalStats::StatsType>
static const std::unordered_map<
std::string, std::function<uint64_t(const TitanInternalStats*, Slice)>>
stats_type_string_map;
static const std::array<
std::string, static_cast<int>(InternalOpType::INTERNAL_OP_ENUM_MAX)>
......@@ -135,20 +130,14 @@ class TitanInternalStats {
std::array<InternalOpStats,
static_cast<size_t>(InternalOpType::INTERNAL_OP_ENUM_MAX)>
internal_op_stats_;
std::shared_ptr<BlobStorage> blob_storage_;
};
class TitanStats {
public:
TitanStats(Statistics* stats) : stats_(stats) {}
// TODO: Initialize corresponding internal stats struct for Column families
// created after DB open.
Status Initialize(std::map<uint32_t, TitanCFOptions> cf_options) {
for (auto& opts : cf_options) {
internal_stats_[opts.first] = std::make_shared<TitanInternalStats>();
}
return Status::OK();
}
void InitializeCF(uint32_t cf_id, std::shared_ptr<BlobStorage> blob_storage);
Statistics* statistics() { return stats_; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment