diff --git a/internal/core/src/mmap/Column.h b/internal/core/src/mmap/Column.h index 9a2052ddef..5ff10b8aeb 100644 --- a/internal/core/src/mmap/Column.h +++ b/internal/core/src/mmap/Column.h @@ -38,6 +38,7 @@ #include "common/FieldDataInterface.h" #include "common/Array.h" #include "knowhere/dataset.h" +#include "storage/prometheus_client.h" namespace milvus { @@ -56,7 +57,8 @@ class ColumnBase { ColumnBase(size_t reserve, const FieldMeta& field_meta) : type_size_(datatype_is_sparse_vector(field_meta.get_data_type()) ? 1 - : field_meta.get_sizeof()) { + : field_meta.get_sizeof()), + is_map_anonymous_(true) { SetPaddingSize(field_meta.get_data_type()); if (datatype_is_variable(field_meta.get_data_type())) { @@ -66,8 +68,9 @@ class ColumnBase { cap_size_ = type_size_ * reserve; // use anon mapping so we are able to free these memory with munmap only + size_t mapped_size = cap_size_ + padding_; data_ = static_cast(mmap(nullptr, - cap_size_ + padding_, + mapped_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, @@ -75,7 +78,9 @@ class ColumnBase { AssertInfo(data_ != MAP_FAILED, "failed to create anon map: {}, map_size={}", strerror(errno), - cap_size_ + padding_); + mapped_size); + + UpdateMetricWhenMmap(mapped_size); } // mmap mode ctor @@ -83,21 +88,21 @@ class ColumnBase { : type_size_(datatype_is_sparse_vector(field_meta.get_data_type()) ? 1 : field_meta.get_sizeof()), + is_map_anonymous_(false), num_rows_(size / type_size_) { SetPaddingSize(field_meta.get_data_type()); size_ = size; cap_size_ = size; - data_ = static_cast(mmap(nullptr, - cap_size_ + padding_, - PROT_READ, - MAP_SHARED, - file.Descriptor(), - 0)); + size_t mapped_size = cap_size_ + padding_; + data_ = static_cast(mmap( + nullptr, mapped_size, PROT_READ, MAP_SHARED, file.Descriptor(), 0)); AssertInfo(data_ != MAP_FAILED, "failed to create file-backed map, err: {}", strerror(errno)); - madvise(data_, cap_size_ + padding_, MADV_WILLNEED); + madvise(data_, mapped_size, MADV_WILLNEED); + + UpdateMetricWhenMmap(mapped_size); } // mmap mode ctor @@ -108,27 +113,29 @@ class ColumnBase { : type_size_(datatype_sizeof(data_type, dim)), num_rows_(size / datatype_sizeof(data_type, dim)), size_(size), - cap_size_(size) { + cap_size_(size), + is_map_anonymous_(false) { SetPaddingSize(data_type); - data_ = static_cast(mmap(nullptr, - cap_size_ + padding_, - PROT_READ, - MAP_SHARED, - file.Descriptor(), - 0)); + size_t mapped_size = cap_size_ + padding_; + data_ = static_cast(mmap( + nullptr, mapped_size, PROT_READ, MAP_SHARED, file.Descriptor(), 0)); AssertInfo(data_ != MAP_FAILED, "failed to create file-backed map, err: {}", strerror(errno)); + + UpdateMetricWhenMmap(mapped_size); } virtual ~ColumnBase() { if (data_ != nullptr) { - if (munmap(data_, cap_size_ + padding_)) { + size_t mapped_size = cap_size_ + padding_; + if (munmap(data_, mapped_size)) { AssertInfo(true, "failed to unmap variable field, err={}", strerror(errno)); } + UpdateMetricWhenMunmap(mapped_size); } } @@ -226,12 +233,14 @@ class ColumnBase { return; } + size_t new_mapped_size = new_size + padding_; auto data = static_cast(mmap(nullptr, - new_size + padding_, + new_mapped_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0)); + UpdateMetricWhenMmap(true, new_mapped_size); AssertInfo(data != MAP_FAILED, "failed to expand map: {}, new_map_size={}", @@ -242,7 +251,9 @@ class ColumnBase { std::memcpy(data, data_, size_); if (munmap(data_, cap_size_ + padding_)) { auto err = errno; - munmap(data, new_size + padding_); + size_t mapped_size = new_size + padding_; + munmap(data, mapped_size); + UpdateMetricWhenMunmap(mapped_size); AssertInfo( false, @@ -250,10 +261,12 @@ class ColumnBase { strerror(err), cap_size_ + padding_); } + UpdateMetricWhenMunmap(cap_size_ + padding_); } data_ = data; cap_size_ = new_size; + is_map_anonymous_ = true; } char* data_{nullptr}; @@ -265,6 +278,42 @@ class ColumnBase { // length in bytes size_t size_{0}; + + private: + void + UpdateMetricWhenMmap(size_t mmaped_size) { + UpdateMetricWhenMmap(is_map_anonymous_, mmaped_size); + } + + void + UpdateMetricWhenMmap(bool is_map_anonymous, size_t mapped_size) { + if (is_map_anonymous) { + milvus::storage::internal_mmap_allocated_space_bytes_anon.Observe( + mapped_size); + milvus::storage::internal_mmap_in_used_space_bytes_anon.Increment( + mapped_size); + } else { + milvus::storage::internal_mmap_allocated_space_bytes_file.Observe( + mapped_size); + milvus::storage::internal_mmap_in_used_space_bytes_file.Increment( + mapped_size); + } + } + + void + UpdateMetricWhenMunmap(size_t mapped_size) { + if (is_map_anonymous_) { + milvus::storage::internal_mmap_in_used_space_bytes_anon.Decrement( + mapped_size); + } else { + milvus::storage::internal_mmap_in_used_space_bytes_file.Decrement( + mapped_size); + } + } + + private: + // is MAP_ANONYMOUS + bool is_map_anonymous_; }; class Column : public ColumnBase { diff --git a/internal/core/src/storage/prometheus_client.cpp b/internal/core/src/storage/prometheus_client.cpp index 2ec0467e28..a4f6c90489 100644 --- a/internal/core/src/storage/prometheus_client.cpp +++ b/internal/core/src/storage/prometheus_client.cpp @@ -31,6 +31,22 @@ const prometheus::Histogram::BucketBoundaries buckets = {1, 32768, 65536}; +const prometheus::Histogram::BucketBoundaries bytesBuckets = { + 1024, // 1k + 8192, // 8k + 65536, // 64k + 262144, // 256k + 524288, // 512k + 1048576, // 1M + 4194304, // 4M + 8388608, // 8M + 16777216, // 16M + 67108864, // 64M + 134217728, // 128M + 268435456, // 256M + 536870912, // 512M + 1073741824}; // 1G + const std::unique_ptr prometheusClient = std::make_unique(); @@ -131,4 +147,32 @@ DEFINE_PROMETHEUS_COUNTER(internal_storage_op_count_remove_suc, DEFINE_PROMETHEUS_COUNTER(internal_storage_op_count_remove_fail, internal_storage_op_count, removeFailMap) + +// mmap metrics +std::map mmapAllocatedSpaceAnonLabel = { + {"type", "anon"}}; +std::map mmapAllocatedSpaceFileLabel = { + {"type", "file"}}; + +DEFINE_PROMETHEUS_HISTOGRAM_FAMILY(internal_mmap_allocated_space_bytes, + "[cpp]mmap allocated space stats") +DEFINE_PROMETHEUS_HISTOGRAM_WITH_BUCKETS( + internal_mmap_allocated_space_bytes_anon, + internal_mmap_allocated_space_bytes, + mmapAllocatedSpaceAnonLabel, + bytesBuckets) +DEFINE_PROMETHEUS_HISTOGRAM_WITH_BUCKETS( + internal_mmap_allocated_space_bytes_file, + internal_mmap_allocated_space_bytes, + mmapAllocatedSpaceFileLabel, + bytesBuckets) + +DEFINE_PROMETHEUS_GAUGE_FAMILY(internal_mmap_in_used_space_bytes, + "[cpp]mmap in used space stats") +DEFINE_PROMETHEUS_GAUGE(internal_mmap_in_used_space_bytes_anon, + internal_mmap_in_used_space_bytes, + mmapAllocatedSpaceAnonLabel) +DEFINE_PROMETHEUS_GAUGE(internal_mmap_in_used_space_bytes_file, + internal_mmap_in_used_space_bytes, + mmapAllocatedSpaceFileLabel) } // namespace milvus::storage diff --git a/internal/core/src/storage/prometheus_client.h b/internal/core/src/storage/prometheus_client.h index d0157da458..dacfd24dfc 100644 --- a/internal/core/src/storage/prometheus_client.h +++ b/internal/core/src/storage/prometheus_client.h @@ -76,6 +76,8 @@ extern const std::unique_ptr prometheusClient; #define DEFINE_PROMETHEUS_HISTOGRAM(alias, name, labels) \ prometheus::Histogram& alias = \ name##_family.Add(labels, milvus::storage::buckets); +#define DEFINE_PROMETHEUS_HISTOGRAM_WITH_BUCKETS(alias, name, labels, buckets) \ + prometheus::Histogram& alias = name##_family.Add(labels, buckets); #define DECLARE_PROMETHEUS_GAUGE_FAMILY(name_gauge_family) \ extern prometheus::Family& name_gauge_family; @@ -112,4 +114,12 @@ DECLARE_PROMETHEUS_COUNTER(internal_storage_op_count_list_suc); DECLARE_PROMETHEUS_COUNTER(internal_storage_op_count_list_fail); DECLARE_PROMETHEUS_COUNTER(internal_storage_op_count_remove_suc); DECLARE_PROMETHEUS_COUNTER(internal_storage_op_count_remove_fail); + +// mmap metrics +DECLARE_PROMETHEUS_HISTOGRAM_FAMILY(internal_mmap_allocated_space_bytes); +DECLARE_PROMETHEUS_HISTOGRAM(internal_mmap_allocated_space_bytes_anon); +DECLARE_PROMETHEUS_HISTOGRAM(internal_mmap_allocated_space_bytes_file); +DECLARE_PROMETHEUS_GAUGE_FAMILY(internal_mmap_in_used_space_bytes); +DECLARE_PROMETHEUS_GAUGE(internal_mmap_in_used_space_bytes_anon); +DECLARE_PROMETHEUS_GAUGE(internal_mmap_in_used_space_bytes_file); } // namespace milvus::storage diff --git a/internal/core/unittest/test_storage.cpp b/internal/core/unittest/test_storage.cpp index 5b25d247de..624237633c 100644 --- a/internal/core/unittest/test_storage.cpp +++ b/internal/core/unittest/test_storage.cpp @@ -146,7 +146,9 @@ TEST_F(StorageTest, GetStorageMetrics) { std::vector res = split(currentLine, " "); EXPECT_EQ(4, res.size()); familyName = res[2]; - EXPECT_EQ(true, res[3] == "counter" || res[3] == "histogram"); + EXPECT_EQ(true, + res[3] == "gauge" || res[3] == "counter" || + res[3] == "histogram"); continue; } EXPECT_EQ(true, familyName.length() > 0);