Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/cn/mbvar_c++.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ public:
```

### get_stats

根据指定label获取对应的单维度统计项bvar。

get_stats除了支持(默认)std::list<std::string>参数类型,也支持自定义参数类型,满足以下条件:
Expand All @@ -421,6 +422,12 @@ get_stats除了支持(默认)std::list<std::string>参数类型,也支持

推荐使用不需要分配内存的容器(例如,std::array、absl::InlinedVector)和不需要拷贝字符串的数据结构(例如,const char*、std::string_view、butil::StringPieces),可以提高性能。

bvar::MultiDimension的模板参数Shared,默认为false:
1. 如果Shared等于false,get_stats返回模板参数T的指针,例如bvar::Adder<int>*。
2. 如果Shared等于true,get_stats返回模板参数T的shared_ptr,例如std::shared_ptr\<bvar::Adder<int>\>。

**注意**:因为shared_ptr的开销,Shared等于true的性能会比Shared等于false的性能差一些。

```c++
#include <bvar/bvar.h>
#include <bvar/multi_dimension.h>
Expand Down Expand Up @@ -523,6 +530,20 @@ int request_count = get_request_count(request_label_list);
* store(bvar)
* return bvar

### delete_stats

根据指定label删除对应的单维度统计项bvar。

bvar::MultiDimension的模板参数Shared,默认为false:
1. 如果Shared等于false,get_stats返回的是模板参数T的指针,delete_stats无法保证没有使用者,所以无法安全删除bvar。
2. 如果Shared等于true,get_stats返回的是模板参数T的shared_ptr,delete_stats可以安全删除bvar。

### clear_stats

清理所有单维度统计项bvar。

安全性同样受bvar::MultiDimension的模板参数Shared的影响,见delete_stats一节说明。

**bvar的生命周期**

label对应的单维度统计项bvar存储在多维度统计项(mbvar)中,当mbvar析构的时候会释放自身所有bvar,所以用户必须保证在mbvar的生命周期之内操作bvar,在mbvar生命周期外访问bvar的行为未定义,极有可能出core。
Expand Down
10 changes: 4 additions & 6 deletions src/bvar/detail/combiner.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,10 @@ friend class GlobalValue<self_type>;
//
// NOTE: Only available to non-atomic types.
template <typename Op>
void merge_global(const Op &op, self_shared_type c = NULL) {
if (NULL == c) {
c = combiner.lock();
}
if (NULL != c) {
GlobalValue<self_type> g(this, c.get());
void merge_global(const Op &op, self_shared_type& c) {
const self_shared_type& c_ref = NULL != c ? c : combiner.lock();
if (NULL != c_ref) {
GlobalValue<self_type> g(this, c_ref.get());
element.merge_global(op, g);
}
}
Expand Down
57 changes: 44 additions & 13 deletions src/bvar/multi_dimension.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#ifndef BVAR_MULTI_DIMENSION_H
#define BVAR_MULTI_DIMENSION_H

#include <memory>
#include <type_traits>
#include "butil/logging.h" // LOG
#include "butil/macros.h" // BAIDU_CASSERT
#include "butil/scoped_lock.h" // BAIDU_SCOPE_LOCK
Expand All @@ -35,8 +37,15 @@ namespace bvar {
// 2. KeyType::value_type must be std::string.
// 3. KeyType::size() returns the number of labels.
// 4. KeyType::push_back() adds a label to the end of the container.
template <typename T, typename KeyType = std::list<std::string>>
//
// If `Shared' is false, `get_stats' returns a raw pointer,
// `delete_stats' and `clear_stats' are not thread safe.
// If `Shared' is true, `get_stats` returns a shared_ptr,
// `delete_stats' and `clear_stats' are thread safe.
// Note: The shared mode may be less performant than the non-shared mode.
template <typename T, typename KeyType = std::list<std::string>, bool Shared = false>
class MultiDimension : public MVariable<KeyType> {
typedef std::shared_ptr<T> shared_value_type;
public:
enum STATS_OP {
READ_ONLY,
Expand All @@ -45,7 +54,7 @@ class MultiDimension : public MVariable<KeyType> {

typedef KeyType key_type;
typedef T value_type;
typedef T* value_ptr_type;
typedef typename std::conditional<Shared, shared_value_type, T*>::type value_ptr_type;
typedef MVariable<key_type> Base;

struct KeyHash {
Expand Down Expand Up @@ -102,11 +111,15 @@ class MultiDimension : public MVariable<KeyType> {
// 2. K::value_type must be able to convert to std::string and butil::StringPiece
// through operator std::string() function and operator butil::StringPiece() function.
// 3. K::value_type must be able to compare with std::string.
//
// Returns a shared_ptr if `Shared' is true, otherwise returns a raw pointer.
template <typename K = key_type>
T* get_stats(const K& labels_value) {
value_ptr_type get_stats(const K& labels_value) {
return get_stats_impl(labels_value, READ_OR_INSERT);
}

// `delete_stats' and `clear_stats' are thread safe
// if `Shared' is true, otherwise not.
// Remove stat so those not count and dump
template <typename K = key_type>
void delete_stats(const K& labels_value);
Expand All @@ -133,25 +146,26 @@ class MultiDimension : public MVariable<KeyType> {
// Return real bvar pointer if labels_name exist, NULL otherwise.
// CAUTION!!! Just For Debug!!!
template <typename K = key_type>
T* get_stats_read_only(const K& labels_value) {
value_ptr_type get_stats_read_only(const K& labels_value) {
return get_stats_impl(labels_value);
}

// Get real bvar pointer object
// Return real bvar pointer if labels_name exist, otherwise(not exist) create bvar pointer.
// CAUTION!!! Just For Debug!!!
template <typename K = key_type>
T* get_stats_read_or_insert(const K& labels_value, bool* do_write = NULL) {
value_ptr_type get_stats_read_or_insert(const K& labels_value, bool* do_write = NULL) {
return get_stats_impl(labels_value, READ_OR_INSERT, do_write);
}
#endif

private:
template <typename K>
T* get_stats_impl(const K& labels_value);
value_ptr_type get_stats_impl(const K& labels_value);

template <typename K>
T* get_stats_impl(const K& labels_value, STATS_OP stats_op, bool* do_write = NULL);
value_ptr_type get_stats_impl(
const K& labels_value, STATS_OP stats_op, bool* do_write = NULL);

template <typename K>
static typename std::enable_if<butil::is_same<K, key_type>::value>::type
Expand All @@ -162,11 +176,8 @@ class MultiDimension : public MVariable<KeyType> {
template <typename K>
static typename std::enable_if<!butil::is_same<K, key_type>::value>::type
insert_metrics_map(MetricMap& bg, const K& labels_value, op_value_type metric) {
key_type labels_value_str;
for (auto& label : labels_value) {
// key_type::value_type must be able to convert to std::string.
labels_value_str.push_back(std::string(label));
}
// key_type::value_type must be able to convert to std::string.
key_type labels_value_str(labels_value.cbegin(), labels_value.cend());
bg.insert(labels_value_str, metric);
}

Expand All @@ -192,7 +203,27 @@ class MultiDimension : public MVariable<KeyType> {
void delete_stats();

static size_t init_flatmap(MetricMap& bg);


// If Shared is true, return std::shared_ptr, otherwise return raw pointer.
template <bool S = Shared>
typename std::enable_if<S, value_ptr_type>::type new_value() {
return std::make_shared<value_type>();
}
template <bool S = Shared>
typename std::enable_if<!S, value_ptr_type>::type new_value() {
return new value_type();
}

// If Shared is true, reset std::shared_ptr, otherwise delete raw pointer.
template <bool S = Shared>
typename std::enable_if<S>::type delete_value(value_ptr_type& v) {
v.reset();
}
template <bool S = Shared>
typename std::enable_if<!S>::type delete_value(value_ptr_type& v) {
delete v;
}

size_t _max_stats_count;
MetricMapDBD _metric_map;
};
Expand Down
Loading
Loading