diff --git a/src/memgraph.cpp b/src/memgraph.cpp index aba536761..983dd61f9 100644 --- a/src/memgraph.cpp +++ b/src/memgraph.cpp @@ -9,6 +9,7 @@ // by the Apache License, Version 2.0, included in the file // licenses/APL.txt. +#include <cstdint> #include "audit/log.hpp" #include "communication/metrics.hpp" #include "communication/websocket/auth.hpp" @@ -48,6 +49,7 @@ namespace { constexpr const char *kMgUser = "MEMGRAPH_USER"; constexpr const char *kMgPassword = "MEMGRAPH_PASSWORD"; constexpr const char *kMgPassfile = "MEMGRAPH_PASSFILE"; +constexpr uint64_t kMgVmMaxMapCount = 262144; // TODO: move elsewhere so that we can remove need of interpreter.hpp void InitFromCypherlFile(memgraph::query::InterpreterContext &ctx, memgraph::dbms::DatabaseAccess &db_acc, @@ -207,6 +209,17 @@ int main(int argc, char **argv) { std::cout << "You are running Memgraph v" << gflags::VersionString() << std::endl; std::cout << "To get started with Memgraph, visit https://memgr.ph/start" << std::endl; + const auto vm_max_map_count = memgraph::utils::GetVmMaxMapCount(); + if (vm_max_map_count.has_value()) { + if (vm_max_map_count.value() < kMgVmMaxMapCount) { + std::cout << "Max virtual memory areas vm.max_map_count " << vm_max_map_count.value() + << " is too low, increase to at least " << kMgVmMaxMapCount << std::endl; + } + } else { + std::cout << "Can't get info on vm.max_map_count, check whether it is too low, vm.max_map_count is at least " + << kMgVmMaxMapCount << std::endl; + } + auto data_directory = std::filesystem::path(FLAGS_data_directory); memgraph::utils::EnsureDirOrDie(data_directory); diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index 7e3ba3dec..ddfc0681b 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -95,6 +95,7 @@ #include "utils/on_scope_exit.hpp" #include "utils/readable_size.hpp" #include "utils/settings.hpp" +#include "utils/stat.hpp" #include "utils/string.hpp" #include "utils/tsc.hpp" #include "utils/typeinfo.hpp" @@ -3092,11 +3093,15 @@ PreparedQuery PrepareSystemInfoQuery(ParsedQuery parsed_query, bool in_explicit_ handler = [storage = current_db.db_acc_->get()->storage(), interpreter_isolation_level, next_transaction_isolation_level] { auto info = storage->GetBaseInfo(); + const auto vm_max_map_count = utils::GetVmMaxMapCount(); + const int64_t vm_max_map_count_storage_info = + vm_max_map_count.has_value() ? vm_max_map_count.value() : memgraph::utils::VM_MAX_MAP_COUNT_DEFAULT; std::vector<std::vector<TypedValue>> results{ {TypedValue("name"), TypedValue(storage->id())}, {TypedValue("vertex_count"), TypedValue(static_cast<int64_t>(info.vertex_count))}, {TypedValue("edge_count"), TypedValue(static_cast<int64_t>(info.edge_count))}, {TypedValue("average_degree"), TypedValue(info.average_degree)}, + {TypedValue("vm_max_map_count"), TypedValue(vm_max_map_count_storage_info)}, {TypedValue("memory_res"), TypedValue(utils::GetReadableSize(static_cast<double>(info.memory_res)))}, {TypedValue("disk_usage"), TypedValue(utils::GetReadableSize(static_cast<double>(info.disk_usage)))}, {TypedValue("memory_tracked"), diff --git a/src/storage/v2/inmemory/storage.cpp b/src/storage/v2/inmemory/storage.cpp index 44c8ac218..c06b204b0 100644 --- a/src/storage/v2/inmemory/storage.cpp +++ b/src/storage/v2/inmemory/storage.cpp @@ -20,6 +20,7 @@ #include "storage/v2/inmemory/replication/replication_client.hpp" #include "storage/v2/inmemory/unique_constraints.hpp" #include "utils/resource_lock.hpp" +#include "utils/stat.hpp" namespace memgraph::storage { diff --git a/src/telemetry/collectors.cpp b/src/telemetry/collectors.cpp index db5517e3e..c36c6abf9 100644 --- a/src/telemetry/collectors.cpp +++ b/src/telemetry/collectors.cpp @@ -78,8 +78,12 @@ const nlohmann::json GetResourceUsage(std::filesystem::path root_directory) { } auto cpu_total = GetCpuUsage(pid); cpu["usage"] = cpu_total.second; - - return {{"cpu", cpu}, {"memory", utils::GetMemoryRES()}, {"disk", utils::GetDirDiskUsage(root_directory)}}; + const auto vm_max_map_count = utils::GetVmMaxMapCount(); + return {{"cpu", cpu}, + {"memory", utils::GetMemoryRES()}, + {"disk", utils::GetDirDiskUsage(root_directory)}, + {"vm_max_map_count", + vm_max_map_count.has_value() ? *vm_max_map_count : memgraph::utils::VM_MAX_MAP_COUNT_DEFAULT}}; } } // namespace memgraph::telemetry diff --git a/src/utils/stat.hpp b/src/utils/stat.hpp index a14973fd7..7e4fab29b 100644 --- a/src/utils/stat.hpp +++ b/src/utils/stat.hpp @@ -11,7 +11,9 @@ #pragma once +#include <cstddef> #include <filesystem> +#include <optional> #include <unistd.h> @@ -20,6 +22,8 @@ namespace memgraph::utils { +static constexpr int64_t VM_MAX_MAP_COUNT_DEFAULT{-1}; + /// Returns the number of bytes a directory is using on disk. If the given path /// isn't a directory, zero will be returned. template <bool IgnoreSymlink = true> @@ -54,4 +58,20 @@ inline uint64_t GetMemoryRES() { return memory; } +/// Returns the size of vm.max_map_count +inline std::optional<int64_t> GetVmMaxMapCount() { + auto vm_max_map_count_data = utils::ReadLines("/proc/sys/vm/max_map_count"); + if (vm_max_map_count_data.empty()) { + return std::nullopt; + } + if (vm_max_map_count_data.size() != 1) { + return std::nullopt; + } + const auto parts{utils::Split(vm_max_map_count_data[0])}; + if (parts.size() != 1) { + return std::nullopt; + } + return std::stoi(parts[0]); +} + } // namespace memgraph::utils diff --git a/tests/e2e/configuration/storage_info.py b/tests/e2e/configuration/storage_info.py index c73656ddb..042a57b08 100644 --- a/tests/e2e/configuration/storage_info.py +++ b/tests/e2e/configuration/storage_info.py @@ -53,10 +53,15 @@ def test_does_default_config_match(): config = cursor.fetchall() # The default value of these is dependent on the given machine. - machine_dependent_configurations = ["memory_res", "disk_usage", "memory_tracked", "allocation_limit"] - + machine_dependent_configurations = [ + "memory_res", + "disk_usage", + "memory_tracked", + "allocation_limit", + "vm_max_map_count", + ] # Number of different data-points returned by SHOW STORAGE INFO - assert len(config) == 12 + assert len(config) == 13 for conf in config: conf_name = conf[0] diff --git a/tests/integration/telemetry/server.py b/tests/integration/telemetry/server.py index f3c8450b0..3336c3588 100755 --- a/tests/integration/telemetry/server.py +++ b/tests/integration/telemetry/server.py @@ -148,6 +148,7 @@ def verify_storage(storage, args): assert "cpu" in item["data"]["resources"] assert "memory" in item["data"]["resources"] assert "disk" in item["data"]["resources"] + assert "vm_max_map_count" in item["data"]["resources"] assert "uptime" in item["data"] uptime = item["data"]["uptime"]