diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2017-09-20 22:09:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-20 22:09:10 +0200 |
commit | 3a387cb98ecd1bbcdef7e6d3bf0c3c8e58cab751 (patch) | |
tree | 7a9b39625444d1e70c8fb399836a308647e289bb /searchcore | |
parent | aaf3e48ef7510d901e078357e15f700494942139 (diff) | |
parent | 07875f4607dfa88f174f1595a47d0c612e40a599 (diff) |
Merge pull request #3459 from vespa-engine/geirst/fix-disk-and-memory-usage-sampling-for-docker
Geirst/fix disk and memory usage sampling for docker
Diffstat (limited to 'searchcore')
13 files changed, 235 insertions, 126 deletions
diff --git a/searchcore/src/tests/proton/attribute/attributeflush_test.cpp b/searchcore/src/tests/proton/attribute/attributeflush_test.cpp index ecb39af61bc..a2ffcda094b 100644 --- a/searchcore/src/tests/proton/attribute/attributeflush_test.cpp +++ b/searchcore/src/tests/proton/attribute/attributeflush_test.cpp @@ -606,8 +606,8 @@ Test::requireThatFlushedAttributeCanBeLoaded(const HwInfo &hwInfo) void Test::requireThatFlushedAttributeCanBeLoaded() { - TEST_DO(requireThatFlushedAttributeCanBeLoaded(HwInfo(false))); - TEST_DO(requireThatFlushedAttributeCanBeLoaded(HwInfo(true))); + TEST_DO(requireThatFlushedAttributeCanBeLoaded(HwInfo(0, false, 0))); + TEST_DO(requireThatFlushedAttributeCanBeLoaded(HwInfo(0, true, 0))); } int diff --git a/searchcore/src/tests/proton/common/hw_info_sampler/hw_info_sampler_test.cpp b/searchcore/src/tests/proton/common/hw_info_sampler/hw_info_sampler_test.cpp index f9745d7fd03..3fd2802f059 100644 --- a/searchcore/src/tests/proton/common/hw_info_sampler/hw_info_sampler_test.cpp +++ b/searchcore/src/tests/proton/common/hw_info_sampler/hw_info_sampler_test.cpp @@ -44,7 +44,7 @@ struct Fixture TEST_F("Test that hw_info_sampler uses override info", Fixture) { - Config samplerCfg(75.0, 100.0, sampleLen); + Config samplerCfg(0, 75.0, 100.0, sampleLen, 0); HwInfoSampler sampler(test_dir, samplerCfg); EXPECT_EQUAL(75.0, sampler.diskWriteSpeed()); EXPECT_NOT_EQUAL(0, time_point_to_long(sampler.sampleTime())); @@ -57,7 +57,7 @@ TEST_F("Test that hw_info_sampler uses saved info", Fixture) builder.disk.writespeed = 72.0; builder.disk.sampletime = time_point_to_long(Clock::now()); f.writeConfig(builder); - Config samplerCfg(0.0, 70.0, sampleLen); + Config samplerCfg(0, 0.0, 70.0, sampleLen, 0); HwInfoSampler sampler(test_dir, samplerCfg); EXPECT_EQUAL(builder.disk.writespeed, sampler.diskWriteSpeed()); EXPECT_EQUAL(builder.disk.sampletime, time_point_to_long(sampler.sampleTime())); @@ -66,7 +66,7 @@ TEST_F("Test that hw_info_sampler uses saved info", Fixture) TEST_F("Test that hw_info_sampler can sample disk write speed", Fixture) { - Config samplerCfg(0.0, 100.0, sampleLen); + Config samplerCfg(0, 0.0, 100.0, sampleLen, 0); HwInfoSampler sampler(test_dir, samplerCfg); ASSERT_NOT_EQUAL(0.0, sampler.diskWriteSpeed()); ASSERT_NOT_EQUAL(0, time_point_to_long(sampler.sampleTime())); @@ -76,6 +76,34 @@ TEST_F("Test that hw_info_sampler can sample disk write speed", Fixture) time_point_to_long(sampler2.sampleTime())); } +TEST_F("require that disk size can be specified", Fixture) +{ + Config samplerCfg(1024, 1.0, 0.0, sampleLen, 0); + HwInfoSampler sampler(test_dir, samplerCfg); + EXPECT_EQUAL(1024u, sampler.hwInfo().diskSizeBytes()); +} + +TEST_F("require that disk size can be sampled", Fixture) +{ + Config samplerCfg(0, 1.0, 0.0, sampleLen, 0); + HwInfoSampler sampler(test_dir, samplerCfg); + EXPECT_GREATER(sampler.hwInfo().diskSizeBytes(), 0u); +} + +TEST_F("require that memory size can be specified", Fixture) +{ + Config samplerCfg(0, 1.0, 0.0, sampleLen, 1024); + HwInfoSampler sampler(test_dir, samplerCfg); + EXPECT_EQUAL(1024u, sampler.hwInfo().memorySizeBytes()); +} + +TEST_F("require that memory size can be sampled", Fixture) +{ + Config samplerCfg(0, 1.0, 0.0, sampleLen, 0); + HwInfoSampler sampler(test_dir, samplerCfg); + EXPECT_GREATER(sampler.hwInfo().memorySizeBytes(), 0u); +} + TEST_MAIN() { vespalib::rmdir(test_dir, true); diff --git a/searchcore/src/tests/proton/server/disk_mem_usage_filter/disk_mem_usage_filter_test.cpp b/searchcore/src/tests/proton/server/disk_mem_usage_filter/disk_mem_usage_filter_test.cpp index 5d8a647f675..05d53c0bf18 100644 --- a/searchcore/src/tests/proton/server/disk_mem_usage_filter/disk_mem_usage_filter_test.cpp +++ b/searchcore/src/tests/proton/server/disk_mem_usage_filter/disk_mem_usage_filter_test.cpp @@ -1,9 +1,11 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include <vespa/vespalib/testkit/testapp.h> +#include <vespa/searchcore/proton/common/hw_info.h> #include <vespa/searchcore/proton/server/disk_mem_usage_filter.h> using proton::DiskMemUsageFilter; +using proton::HwInfo; namespace fs = std::experimental::filesystem; @@ -16,9 +18,9 @@ struct Fixture using Config = DiskMemUsageFilter::Config; Fixture() - : _filter(64 * 1024 * 1024) + : _filter(HwInfo(100, false, 64 * 1024 * 1024)) { - _filter.setDiskStats({.capacity = 100, .free = 100, .available=100}); + _filter.setDiskStats(0); _filter.setMemoryStats(vespalib::ProcessMemoryStats(10000000, 10000001, 10000002, @@ -41,7 +43,7 @@ struct Fixture } void triggerDiskLimit() { - _filter.setDiskStats({.capacity = 100, .free = 20, .available=10}); + _filter.setDiskStats(90); } void triggerMemoryLimit() @@ -76,7 +78,7 @@ TEST_F("Check that disk limit can be reached", Fixture) "action: \"add more content nodes\", " "reason: \"disk used (0.9) > disk limit (0.8)\", " "stats: { " - "capacity: 100, free: 20, available: 10, diskUsed: 0.9, diskLimit: 0.8}}"); + "capacity: 100, used: 90, diskUsed: 0.9, diskLimit: 0.8}}"); } TEST_F("Check that memory limit can be reached", Fixture) @@ -108,7 +110,7 @@ TEST_F("Check that both disk limit and memory limit can be reached", Fixture) "action: \"add more content nodes\", " "reason: \"disk used (0.9) > disk limit (0.8)\", " "stats: { " - "capacity: 100, free: 20, available: 10, diskUsed: 0.9, diskLimit: 0.8}}"); + "capacity: 100, used: 90, diskUsed: 0.9, diskLimit: 0.8}}"); } TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchcore/src/vespa/searchcore/proton/common/CMakeLists.txt b/searchcore/src/vespa/searchcore/proton/common/CMakeLists.txt index dec686d3070..cdca446f114 100644 --- a/searchcore/src/vespa/searchcore/proton/common/CMakeLists.txt +++ b/searchcore/src/vespa/searchcore/proton/common/CMakeLists.txt @@ -22,4 +22,5 @@ vespa_add_library(searchcore_pcommon STATIC DEPENDS searchcore_proton_metrics searchcore_fconfig + stdc++fs ) diff --git a/searchcore/src/vespa/searchcore/proton/common/hw_info.h b/searchcore/src/vespa/searchcore/proton/common/hw_info.h index 06efaec18f2..e98af734ba3 100644 --- a/searchcore/src/vespa/searchcore/proton/common/hw_info.h +++ b/searchcore/src/vespa/searchcore/proton/common/hw_info.h @@ -2,6 +2,8 @@ #pragma once +#include <cstdint> + namespace proton { /* @@ -9,19 +11,30 @@ namespace proton { */ class HwInfo { + uint64_t _diskSizeBytes; bool _slowDisk; + uint64_t _memorySizeBytes; + public: HwInfo() - : _slowDisk(false) + : _diskSizeBytes(0), + _slowDisk(false), + _memorySizeBytes(0) { } - HwInfo(bool slowDisk_in) - : _slowDisk(slowDisk_in) + HwInfo(uint64_t diskSizeBytes_in, + bool slowDisk_in, + uint64_t memorySizeBytes_in) + : _diskSizeBytes(diskSizeBytes_in), + _slowDisk(slowDisk_in), + _memorySizeBytes(memorySizeBytes_in) { } + uint64_t diskSizeBytes() const { return _diskSizeBytes; } bool slowDisk() const { return _slowDisk; } + uint64_t memorySizeBytes() const { return _memorySizeBytes; } }; } diff --git a/searchcore/src/vespa/searchcore/proton/common/hw_info_sampler.cpp b/searchcore/src/vespa/searchcore/proton/common/hw_info_sampler.cpp index 73bb20c712a..0d5839e9bec 100644 --- a/searchcore/src/vespa/searchcore/proton/common/hw_info_sampler.cpp +++ b/searchcore/src/vespa/searchcore/proton/common/hw_info_sampler.cpp @@ -1,13 +1,14 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "hw_info_sampler.h" -#include <vespa/config/config.h> #include <vespa/config/common/configholder.h> +#include <vespa/config/config.h> #include <vespa/config/file/filesource.h> -#include <vespa/searchcore/config/config-hwinfo.h> #include <vespa/config/print/fileconfigwriter.h> -#include <vespa/vespalib/io/fileutil.h> #include <vespa/fastos/file.h> +#include <vespa/searchcore/config/config-hwinfo.h> +#include <vespa/vespalib/io/fileutil.h> +#include <experimental/filesystem> using config::ConfigHandle; using config::ConfigSubscriber; @@ -22,6 +23,26 @@ namespace proton { namespace { +uint64_t +sampleDiskSizeBytes(const std::string &pathStr, const HwInfoSampler::Config &cfg) +{ + if (cfg.diskSizeBytes != 0) { + return cfg.diskSizeBytes; + } + std::experimental::filesystem::path path(pathStr); + auto space_info = std::experimental::filesystem::space(path); + return space_info.capacity; +} + +uint64_t +sampleMemorySizeBytes(const HwInfoSampler::Config &cfg) +{ + if (cfg.memorySizeBytes != 0) { + return cfg.memorySizeBytes; + } + return sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE); +} + std::unique_ptr<HwinfoConfig> readConfig(const vespalib::string &path) { FileSpec spec(path + "/" + "hwinfo.cfg"); ConfigSubscriber s(spec); @@ -78,20 +99,11 @@ HwInfoSampler::HwInfoSampler(const vespalib::string &path, const Config &config) : _hwInfo(), _sampleTime(), - _diskWriteSpeed(0.0) + _diskSizeBytes(sampleDiskSizeBytes(path, config)), + _diskWriteSpeed(0.0), + _memorySizeBytes(sampleMemorySizeBytes(config)) { - if (config._diskWriteSpeedOverride != 0) { - _diskWriteSpeed = config._diskWriteSpeedOverride; - _sampleTime = Clock::now(); - } else { - auto cfg = readConfig(path); - if (cfg && cfg->disk.sampletime != 0.0) { - _sampleTime = std::chrono::time_point<Clock>(std::chrono::seconds(cfg->disk.sampletime)); - _diskWriteSpeed = cfg->disk.writespeed; - } else { - sample(path, config); - } - } + setDiskWriteSpeed(path, config); setup(config); } @@ -102,15 +114,32 @@ HwInfoSampler::~HwInfoSampler() void HwInfoSampler::setup(const Config &config) { - bool slowDisk = _diskWriteSpeed < config._slowWriteSpeedLimit; - _hwInfo = HwInfo(slowDisk); + bool slowDisk = _diskWriteSpeed < config.slowWriteSpeedLimit; + _hwInfo = HwInfo(_diskSizeBytes, slowDisk, _memorySizeBytes); +} + +void +HwInfoSampler::setDiskWriteSpeed(const vespalib::string &path, const Config &config) +{ + if (config.diskWriteSpeedOverride != 0) { + _diskWriteSpeed = config.diskWriteSpeedOverride; + _sampleTime = Clock::now(); + } else { + auto cfg = readConfig(path); + if (cfg && cfg->disk.sampletime != 0.0) { + _sampleTime = std::chrono::time_point<Clock>(std::chrono::seconds(cfg->disk.sampletime)); + _diskWriteSpeed = cfg->disk.writespeed; + } else { + sampleDiskWriteSpeed(path, config); + } + } } void -HwInfoSampler::sample(const vespalib::string &path, const Config &config) +HwInfoSampler::sampleDiskWriteSpeed(const vespalib::string &path, const Config &config) { size_t minDiskWriteLen = 1024u * 1024u; - size_t diskWriteLen = config._diskSampleWriteSize; + size_t diskWriteLen = config.diskSampleWriteSize; diskWriteLen = std::max(diskWriteLen, minDiskWriteLen); _sampleTime = Clock::now(); _diskWriteSpeed = measureDiskWriteSpeed(path, diskWriteLen); diff --git a/searchcore/src/vespa/searchcore/proton/common/hw_info_sampler.h b/searchcore/src/vespa/searchcore/proton/common/hw_info_sampler.h index 22af2d32786..208dac0ee44 100644 --- a/searchcore/src/vespa/searchcore/proton/common/hw_info_sampler.h +++ b/searchcore/src/vespa/searchcore/proton/common/hw_info_sampler.h @@ -16,16 +16,22 @@ class HwInfoSampler { public: struct Config { - double _diskWriteSpeedOverride; - double _slowWriteSpeedLimit; - uint64_t _diskSampleWriteSize; - - Config(double diskWriteSpeedOverride, - double slowWriteSpeedLimit, - double diskSampleWriteSize) - : _diskWriteSpeedOverride(diskWriteSpeedOverride), - _slowWriteSpeedLimit(slowWriteSpeedLimit), - _diskSampleWriteSize(diskSampleWriteSize) + uint64_t diskSizeBytes; + double diskWriteSpeedOverride; + double slowWriteSpeedLimit; + uint64_t diskSampleWriteSize; + uint64_t memorySizeBytes; + + Config(uint64_t diskSizeBytes_, + double diskWriteSpeedOverride_, + double slowWriteSpeedLimit_, + double diskSampleWriteSize_, + uint64_t memorySizeBytes_) + : diskSizeBytes(diskSizeBytes_), + diskWriteSpeedOverride(diskWriteSpeedOverride_), + slowWriteSpeedLimit(slowWriteSpeedLimit_), + diskSampleWriteSize(diskSampleWriteSize_), + memorySizeBytes(memorySizeBytes_) { } }; @@ -34,10 +40,13 @@ private: HwInfo _hwInfo; using Clock = std::chrono::system_clock; Clock::time_point _sampleTime; + uint64_t _diskSizeBytes; double _diskWriteSpeed; + uint64_t _memorySizeBytes; void setup(const Config &config); - void sample(const vespalib::string &path, const Config &config); + void setDiskWriteSpeed(const vespalib::string &path, const Config &config); + void sampleDiskWriteSpeed(const vespalib::string &path, const Config &config); public: HwInfoSampler(const vespalib::string &path, const Config &config); ~HwInfoSampler(); diff --git a/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_filter.cpp b/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_filter.cpp index d489f477df2..307eed94095 100644 --- a/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_filter.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_filter.cpp @@ -3,6 +3,7 @@ #include "disk_mem_usage_filter.h" #include "i_disk_mem_usage_listener.h" #include <vespa/log/log.h> +#include <vespa/searchcore/proton/common/hw_info.h> LOG_SETUP(".proton.server.disk_mem_usage_filter"); @@ -43,12 +44,12 @@ void makeDiskStatsMessage(std::ostream &os, double diskUsed, double diskLimit, - const DiskMemUsageFilter::space_info &diskStats) + const HwInfo &hwInfo, + uint64_t usedDiskSizeBytes) { os << "stats: { "; - os << "capacity: " << diskStats.capacity << ", "; - os << "free: " << diskStats.free << ", "; - os << "available: " << diskStats.available << ", "; + os << "capacity: " << hwInfo.diskSizeBytes() << ", "; + os << "used: " << usedDiskSizeBytes << ", "; os << "diskUsed: " << diskUsed << ", "; os << "diskLimit: " << diskLimit << "}"; } @@ -57,31 +58,31 @@ void makeDiskLimitMessage(std::ostream &os, double diskUsed, double diskLimit, - const DiskMemUsageFilter::space_info &diskStats) + const HwInfo &hwInfo, + uint64_t usedDiskSizeBytes) { os << "diskLimitReached: { "; os << "action: \"add more content nodes\", "; os << "reason: \"disk used (" << diskUsed << ") > disk limit (" << diskLimit << ")\", "; - makeDiskStatsMessage(os, diskUsed, diskLimit, diskStats); + makeDiskStatsMessage(os, diskUsed, diskLimit, hwInfo, usedDiskSizeBytes); os << "}"; } - vespalib::string makeUnblockingMessage(double memoryUsed, double memoryLimit, const vespalib::ProcessMemoryStats &memoryStats, - uint64_t physicalMemory, + const HwInfo &hwInfo, double diskUsed, double diskLimit, - const DiskMemUsageFilter::space_info &diskStats) + uint64_t usedDiskSizeBytes) { std::ostringstream os; os << "memoryLimitOK: { "; - makeMemoryStatsMessage(os, memoryUsed, memoryLimit, memoryStats, physicalMemory); + makeMemoryStatsMessage(os, memoryUsed, memoryLimit, memoryStats, hwInfo.memorySizeBytes()); os << "}, "; os << "diskLimitOK: { "; - makeDiskStatsMessage(os, diskUsed, diskLimit, diskStats); + makeDiskStatsMessage(os, diskUsed, diskLimit, hwInfo, usedDiskSizeBytes); os << "}"; return os.str(); } @@ -97,7 +98,7 @@ DiskMemUsageFilter::recalcState(const Guard &guard) if (memoryUsed > _config._memoryLimit) { hasMessage = true; makeMemoryLimitMessage(message, memoryUsed, - _config._memoryLimit, _memoryStats, _physicalMemory); + _config._memoryLimit, _memoryStats, _hwInfo.memorySizeBytes()); } double diskUsed = getDiskUsedRatio(guard); if (diskUsed > _config._diskLimit) { @@ -105,7 +106,7 @@ DiskMemUsageFilter::recalcState(const Guard &guard) message << ", "; } hasMessage = true; - makeDiskLimitMessage(message, diskUsed, _config._diskLimit, _diskStats); + makeDiskLimitMessage(message, diskUsed, _config._diskLimit, _hwInfo, _usedDiskSizeBytes); } if (hasMessage) { if (_acceptWrite) { @@ -118,10 +119,10 @@ DiskMemUsageFilter::recalcState(const Guard &guard) vespalib::string unblockMsg = makeUnblockingMessage(memoryUsed, _config._memoryLimit, _memoryStats, - _physicalMemory, + _hwInfo, diskUsed, _config._diskLimit, - _diskStats); + _usedDiskSizeBytes); LOG(info, "Write operations are now un-blocked: '%s'", unblockMsg.c_str()); } _state = State(); @@ -137,23 +138,23 @@ DiskMemUsageFilter::getMemoryUsedRatio(const Guard &guard) const { (void) guard; uint64_t unscaledMemoryUsed = _memoryStats.getAnonymousRss(); - return static_cast<double>(unscaledMemoryUsed) / _physicalMemory; + return static_cast<double>(unscaledMemoryUsed) / _hwInfo.memorySizeBytes(); } double DiskMemUsageFilter::getDiskUsedRatio(const Guard &guard) const { (void) guard; - double availableDiskSpaceRatio = static_cast<double>(_diskStats.available) / - static_cast<double>(_diskStats.capacity); - return 1.0 - availableDiskSpaceRatio; + double usedDiskSpaceRatio = static_cast<double>(_usedDiskSizeBytes) / + static_cast<double>(_hwInfo.diskSizeBytes()); + return usedDiskSpaceRatio; } -DiskMemUsageFilter::DiskMemUsageFilter(uint64_t physicalMemory_in) +DiskMemUsageFilter::DiskMemUsageFilter(const HwInfo &hwInfo) : _lock(), + _hwInfo(hwInfo), _memoryStats(), - _physicalMemory(physicalMemory_in), - _diskStats(), + _usedDiskSizeBytes(), _config(), _state(), _acceptWrite(true), @@ -172,10 +173,10 @@ DiskMemUsageFilter::setMemoryStats(vespalib::ProcessMemoryStats memoryStats_in) } void -DiskMemUsageFilter::setDiskStats(space_info diskStats_in) +DiskMemUsageFilter::setDiskStats(uint64_t usedDiskSizeBytes) { Guard guard(_lock); - _diskStats = diskStats_in; + _usedDiskSizeBytes = usedDiskSizeBytes; recalcState(guard); } @@ -194,11 +195,11 @@ DiskMemUsageFilter::getMemoryStats() const return _memoryStats; } -DiskMemUsageFilter::space_info +uint64_t DiskMemUsageFilter::getDiskStats() const { Guard guard(_lock); - return _diskStats; + return _usedDiskSizeBytes; } DiskMemUsageFilter::Config diff --git a/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_filter.h b/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_filter.h index c06d2e2ab0a..1083b969edd 100644 --- a/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_filter.h +++ b/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_filter.h @@ -4,12 +4,12 @@ #include "i_disk_mem_usage_notifier.h" #include "disk_mem_usage_state.h" +#include <vespa/searchcore/proton/common/hw_info.h> #include <vespa/searchcore/proton/persistenceengine/i_resource_write_filter.h> #include <vespa/vespalib/util/process_memory_stats.h> -#include <mutex> #include <atomic> #include <experimental/filesystem> - +#include <mutex> namespace proton { @@ -39,10 +39,10 @@ public: }; private: - mutable Mutex _lock; // protect _memoryStats, _diskStats, _config, _state + mutable Mutex _lock; // protect _memoryStats, _usedDiskSizeBytes, _config, _state + HwInfo _hwInfo; vespalib::ProcessMemoryStats _memoryStats; - uint64_t _physicalMemory; - space_info _diskStats; + uint64_t _usedDiskSizeBytes; Config _config; State _state; std::atomic<bool> _acceptWrite; @@ -55,15 +55,15 @@ private: void notifyDiskMemUsage(const Guard &guard, DiskMemUsageState state); public: - DiskMemUsageFilter(uint64_t physicalMememory_in); + DiskMemUsageFilter(const HwInfo &hwInfo); ~DiskMemUsageFilter(); void setMemoryStats(vespalib::ProcessMemoryStats memoryStats_in); - void setDiskStats(space_info diskStats_in); + void setDiskStats(uint64_t usedDiskSizeBytes); void setConfig(Config config); vespalib::ProcessMemoryStats getMemoryStats() const; - space_info getDiskStats() const; + uint64_t getDiskStats() const; Config getConfig() const; - uint64_t getPhysicalMemory() const { return _physicalMemory; } + const HwInfo &getHwInfo() const { return _hwInfo; } double getMemoryUsedRatio() const; double getDiskUsedRatio() const; bool acceptWriteOperation() const override; diff --git a/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_sampler.cpp b/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_sampler.cpp index fb7d712db9d..09e44c85298 100644 --- a/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_sampler.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_sampler.cpp @@ -3,31 +3,19 @@ #include "disk_mem_usage_sampler.h" #include <vespa/vespalib/util/timer.h> #include <vespa/searchlib/common/lambdatask.h> +#include <experimental/filesystem> #include <unistd.h> using search::makeLambdaTask; namespace proton { -namespace { - -uint64_t getPhysicalMemoryBytes() -{ - // TODO: Temporal workaround for Docker nodes. Remove when this is part of proton.cfg instead. - if (const char *memoryEnv = std::getenv("VESPA_TOTAL_MEMORY_MB")) { - uint64_t physicalMemoryMB = atoll(memoryEnv); - return physicalMemoryMB * 1024u * 1024u; - } else { - return sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE); - } -} - -} // namespace proton:<anonymous> - -DiskMemUsageSampler::DiskMemUsageSampler(const std::string &path_in, +DiskMemUsageSampler::DiskMemUsageSampler(const std::string &protonBaseDir, + const std::string &vespaHomeDir, const Config &config) - : _filter(getPhysicalMemoryBytes()), - _path(path_in), + : _filter(config.hwInfo), + _protonBaseDir(protonBaseDir), + _vespaHomeDir(vespaHomeDir), _sampleInterval(60.0), _periodicTimer() { @@ -43,8 +31,8 @@ void DiskMemUsageSampler::setConfig(const Config &config) { _periodicTimer.reset(); - _filter.setConfig(config._filterConfig); - _sampleInterval = config._sampleInterval; + _filter.setConfig(config.filterConfig); + _sampleInterval = config.sampleInterval; sampleUsage(); _periodicTimer = std::make_unique<vespalib::Timer>(); _periodicTimer->scheduleAtFixedRate(makeLambdaTask([this]() @@ -59,10 +47,35 @@ DiskMemUsageSampler::sampleUsage() sampleDiskUsage(); } +namespace { + +uint64_t +sampleDiskUsageInDirectory(const std::experimental::filesystem::path &path) +{ + uint64_t result = 0; + for (const auto &elem : std::experimental::filesystem::recursive_directory_iterator(path)) { + if (!std::experimental::filesystem::is_directory(elem.path())) { + result += std::experimental::filesystem::file_size(elem.path()); + } + } + return result; +} + +uint64_t +sampleDiskUsageOnFileSystem(const std::experimental::filesystem::path &path) +{ + auto space_info = std::experimental::filesystem::space(path); + return (space_info.capacity - space_info.available); +} + +} + void DiskMemUsageSampler::sampleDiskUsage() { - _filter.setDiskStats(std::experimental::filesystem::space(_path)); + bool slowDisk = _filter.getHwInfo().slowDisk(); + _filter.setDiskStats(slowDisk ? sampleDiskUsageOnFileSystem(_protonBaseDir) : + sampleDiskUsageInDirectory(_vespaHomeDir)); } void diff --git a/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_sampler.h b/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_sampler.h index 198f111f052..e93a121d0e5 100644 --- a/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_sampler.h +++ b/searchcore/src/vespa/searchcore/proton/server/disk_mem_usage_sampler.h @@ -13,7 +13,8 @@ namespace proton { */ class DiskMemUsageSampler { DiskMemUsageFilter _filter; - std::experimental::filesystem::path _path; + std::experimental::filesystem::path _protonBaseDir; + std::experimental::filesystem::path _vespaHomeDir; double _sampleInterval; std::unique_ptr<vespalib::Timer> _periodicTimer; @@ -22,24 +23,30 @@ class DiskMemUsageSampler { void sampleMemoryUsage(); public: struct Config { - DiskMemUsageFilter::Config _filterConfig; - double _sampleInterval; - public: + DiskMemUsageFilter::Config filterConfig; + double sampleInterval; + HwInfo hwInfo; + Config() - : _filterConfig(), - _sampleInterval(60.0) + : filterConfig(), + sampleInterval(60.0), + hwInfo() { } - Config(double memoryLimit_in, double diskLimit_in, - double sampleInterval_in) - : _filterConfig(memoryLimit_in, diskLimit_in), - _sampleInterval(sampleInterval_in) + Config(double memoryLimit_in, + double diskLimit_in, + double sampleInterval_in, + const HwInfo &hwInfo_in) + : filterConfig(memoryLimit_in, diskLimit_in), + sampleInterval(sampleInterval_in), + hwInfo(hwInfo_in) { } }; - DiskMemUsageSampler(const std::string &path_in, + DiskMemUsageSampler(const std::string &protonBaseDir, + const std::string &vespaHomeDir, const Config &config); ~DiskMemUsageSampler(); diff --git a/searchcore/src/vespa/searchcore/proton/server/proton.cpp b/searchcore/src/vespa/searchcore/proton/server/proton.cpp index d95b0fd44d1..09a974d3014 100644 --- a/searchcore/src/vespa/searchcore/proton/server/proton.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/proton.cpp @@ -32,6 +32,8 @@ #include <vespa/searchlib/expression/forcelink.hpp> #include <vespa/log/log.h> +#include <vespa/defaults.h> + LOG_SETUP(".proton.server.proton"); using document::DocumentTypeRepo; @@ -75,12 +77,13 @@ setFS4Compression(const ProtonConfig & proton) } DiskMemUsageSampler::Config -diskMemUsageSamplerConfig(const ProtonConfig &proton) +diskMemUsageSamplerConfig(const ProtonConfig &proton, const HwInfo &hwInfo) { return DiskMemUsageSampler::Config( proton.writefilter.memorylimit, proton.writefilter.disklimit, - proton.writefilter.sampleinterval); + proton.writefilter.sampleinterval, + hwInfo); } } @@ -223,17 +226,21 @@ Proton::init(const BootstrapConfig::SP & configSnapshot) { assert( _initStarted && ! _initComplete ); const ProtonConfig &protonConfig = configSnapshot->getProtonConfig(); - const auto &samplerCfgArgs = protonConfig.hwinfo.disk; - HwInfoSampler::Config samplerCfg(samplerCfgArgs.writespeed, - samplerCfgArgs.slowwritespeedlimit, - samplerCfgArgs.samplewritesize); + const auto &hwDiskCfg = protonConfig.hwinfo.disk; + const auto &hwMemoryCfg = protonConfig.hwinfo.memory; + HwInfoSampler::Config samplerCfg(hwDiskCfg.size, + hwDiskCfg.writespeed, + hwDiskCfg.slowwritespeedlimit, + hwDiskCfg.samplewritesize, + hwMemoryCfg.size); _hwInfoSampler = std::make_unique<HwInfoSampler>(protonConfig.basedir, samplerCfg); _hwInfo = _hwInfoSampler->hwInfo(); setFS4Compression(protonConfig); + vespalib::string vespaHomeDir = vespa::Defaults::vespaHome(); _diskMemUsageSampler = std::make_unique<DiskMemUsageSampler> - (protonConfig.basedir, - diskMemUsageSamplerConfig(protonConfig)); + (protonConfig.basedir, vespaHomeDir, + diskMemUsageSamplerConfig(protonConfig, _hwInfo)); _metricsEngine.reset(new MetricsEngine()); _metricsEngine->addMetricsHook(_metricsHook); @@ -341,7 +348,7 @@ Proton::applyConfig(const BootstrapConfig::SP & configSnapshot) protonConfig.search.memory.limiter.minhits); const DocumentTypeRepo::SP repo = configSnapshot->getDocumentTypeRepoSP(); - _diskMemUsageSampler->setConfig(diskMemUsageSamplerConfig(protonConfig)); + _diskMemUsageSampler->setConfig(diskMemUsageSamplerConfig(protonConfig, _hwInfo)); if (_memoryFlushConfigUpdater) { _memoryFlushConfigUpdater->setConfig(protonConfig.flush.memory); _flushEngine->kick(); diff --git a/searchcore/src/vespa/searchcore/proton/server/resource_usage_explorer.cpp b/searchcore/src/vespa/searchcore/proton/server/resource_usage_explorer.cpp index afe9f6b85d3..7bd01760141 100644 --- a/searchcore/src/vespa/searchcore/proton/server/resource_usage_explorer.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/resource_usage_explorer.cpp @@ -9,11 +9,10 @@ using namespace vespalib::slime; namespace proton { void -convertDiskStatsToSlime(const DiskMemUsageFilter::space_info &stats, Cursor &object) +convertDiskStatsToSlime(const HwInfo &hwInfo, uint64_t usedDiskSizeBytes, Cursor &object) { - object.setLong("capacity", stats.capacity); - object.setLong("free", stats.free); - object.setLong("available", stats.available); + object.setLong("capacity", hwInfo.diskSizeBytes()); + object.setLong("used", usedDiskSizeBytes); } void @@ -39,12 +38,12 @@ ResourceUsageExplorer::get_state(const vespalib::slime::Inserter &inserter, bool Cursor &disk = object.setObject("disk"); disk.setDouble("usedRatio", _usageFilter.getDiskUsedRatio()); disk.setDouble("usedLimit", config._diskLimit); - convertDiskStatsToSlime(_usageFilter.getDiskStats(), disk.setObject("stats")); + convertDiskStatsToSlime(_usageFilter.getHwInfo(), _usageFilter.getDiskStats(), disk.setObject("stats")); Cursor &memory = object.setObject("memory"); memory.setDouble("usedRatio", _usageFilter.getMemoryUsedRatio()); memory.setDouble("usedLimit", config._memoryLimit); - memory.setLong("physicalMemory", _usageFilter.getPhysicalMemory()); + memory.setLong("physicalMemory", _usageFilter.getHwInfo().memorySizeBytes()); convertMemoryStatsToSlime(_usageFilter.getMemoryStats(), memory.setObject("stats")); } else { object.setDouble("disk", _usageFilter.getDiskUsedRatio()); |