diff options
Diffstat (limited to 'searchcore')
19 files changed, 266 insertions, 132 deletions
diff --git a/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.h b/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.h index 2a7115f4d33..160423c7c68 100644 --- a/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.h +++ b/searchcore/src/vespa/searchcore/proton/flushengine/flushengine.h @@ -112,6 +112,11 @@ public: vespalib::ThreadStackExecutor::Stats getExecutorStats() { return _executor.getStats(); } /** + * Returns the underlying executor. Only used for state explorers. + */ + const vespalib::SyncableThreadExecutor& get_executor() const { return _executor; } + + /** * Starts the scheduling thread of this manager. * * @return This, to allow chaining. diff --git a/searchcore/src/vespa/searchcore/proton/matchengine/matchengine.h b/searchcore/src/vespa/searchcore/proton/matchengine/matchengine.h index 34aacdafcad..8adc198bb40 100644 --- a/searchcore/src/vespa/searchcore/proton/matchengine/matchengine.h +++ b/searchcore/src/vespa/searchcore/proton/matchengine/matchengine.h @@ -60,6 +60,11 @@ public: vespalib::ThreadStackExecutor::Stats getExecutorStats() { return _executor.getStats(); } /** + * Returns the underlying executor. Only used for state explorers. + */ + const vespalib::SyncableThreadExecutor& get_executor() const { return _executor; } + + /** * Closes the request handler interface. This will prevent any more data * from entering this object, allowing you to flush all pending operations * without having to safe-guard against input. diff --git a/searchcore/src/vespa/searchcore/proton/metrics/documentdb_tagged_metrics.cpp b/searchcore/src/vespa/searchcore/proton/metrics/documentdb_tagged_metrics.cpp index 3b1a21a7e2f..7b7fcc9e45d 100644 --- a/searchcore/src/vespa/searchcore/proton/metrics/documentdb_tagged_metrics.cpp +++ b/searchcore/src/vespa/searchcore/proton/metrics/documentdb_tagged_metrics.cpp @@ -194,7 +194,8 @@ DocumentDBTaggedMetrics::MatchingMetrics::RankProfileMetrics::DocIdPartition::up } void -DocumentDBTaggedMetrics::MatchingMetrics::RankProfileMetrics::update(const MatchingStats &stats) +DocumentDBTaggedMetrics::MatchingMetrics::RankProfileMetrics::update(const metrics::MetricLockGuard &, + const MatchingStats &stats) { docsMatched.inc(stats.docsMatched()); docsRanked.inc(stats.docsRanked()); diff --git a/searchcore/src/vespa/searchcore/proton/metrics/documentdb_tagged_metrics.h b/searchcore/src/vespa/searchcore/proton/metrics/documentdb_tagged_metrics.h index 26dd52a8577..133df81a9e6 100644 --- a/searchcore/src/vespa/searchcore/proton/metrics/documentdb_tagged_metrics.h +++ b/searchcore/src/vespa/searchcore/proton/metrics/documentdb_tagged_metrics.h @@ -9,6 +9,8 @@ #include <vespa/metrics/valuemetric.h> #include <vespa/searchcore/proton/matching/matching_stats.h> +namespace metrics { class MetricLockGuard; } + namespace proton { /** @@ -154,7 +156,7 @@ struct DocumentDBTaggedMetrics : metrics::MetricSet size_t numDocIdPartitions, metrics::MetricSet *parent); ~RankProfileMetrics() override; - void update(const matching::MatchingStats &stats); + void update(const metrics::MetricLockGuard & guard, const matching::MatchingStats &stats); }; using RankProfileMap = std::map<vespalib::string, RankProfileMetrics::UP>; diff --git a/searchcore/src/vespa/searchcore/proton/server/CMakeLists.txt b/searchcore/src/vespa/searchcore/proton/server/CMakeLists.txt index 81dd8a64a6c..73b7404ce31 100644 --- a/searchcore/src/vespa/searchcore/proton/server/CMakeLists.txt +++ b/searchcore/src/vespa/searchcore/proton/server/CMakeLists.txt @@ -35,6 +35,7 @@ vespa_add_library(searchcore_server STATIC documentretrieverbase.cpp documentsubdbcollection.cpp emptysearchview.cpp + executor_explorer_utils.cpp executor_thread_service.cpp executor_threading_service_explorer.cpp executorthreadingservice.cpp @@ -77,6 +78,7 @@ vespa_add_library(searchcore_server STATIC proton_config_snapshot.cpp proton_configurer.cpp proton_disk_layout.cpp + proton_thread_pools_explorer.cpp prune_session_cache_job.cpp pruneremoveddocumentsjob.cpp putdonecontext.cpp diff --git a/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp b/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp index c7b5aaafbfc..7323744c626 100644 --- a/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/documentdb.cpp @@ -35,6 +35,7 @@ #include <vespa/searchlib/common/gatecallback.h> #include <vespa/vespalib/util/closuretask.h> #include <vespa/vespalib/util/exceptions.h> +#include <vespa/metrics/updatehook.h> #include <vespa/log/log.h> #include <vespa/searchcorespi/index/warmupconfig.h> @@ -102,6 +103,18 @@ findDocumentDB(const ProtonConfig::DocumentdbVector & documentDBs, const vespali return &_G_defaultProtonDocumentDBConfig; } +class MetricsUpdateHook : public metrics::UpdateHook { + DocumentDB &_db; +public: + MetricsUpdateHook(DocumentDB &s) + : metrics::UpdateHook("documentdb-hook"), + _db(s) + {} + void updateMetrics(const MetricLockGuard & guard) override { + _db.updateMetrics(guard); + } +}; + } template <typename FunctionType> @@ -147,7 +160,6 @@ DocumentDB::DocumentDB(const vespalib::string &baseDir, _configCV(), _activeConfigSnapshot(), _activeConfigSnapshotGeneration(0), - _activeConfigSnapshotSerialNum(0u), _validateAndSanitizeDocStore(protonCfg.validateAndSanitizeDocstore == vespa::config::search::core::ProtonConfig::ValidateAndSanitizeDocstore::YES), _initGate(), _clusterStateHandler(_writeService.master()), @@ -156,7 +168,8 @@ DocumentDB::DocumentDB(const vespalib::string &baseDir, _config_store(std::move(config_store)), _sessionManager(std::make_shared<matching::SessionManager>(protonCfg.grouping.sessionmanager.maxentries)), _metricsWireService(metricsWireService), - _metricsHook(*this, _docTypeName.getName(), protonCfg.numthreadspersearch), + _metrics(_docTypeName.getName(), protonCfg.numthreadspersearch), + _metricsHook(std::make_unique<MetricsUpdateHook>(*this)), _feedView(), _refCount(), _syncFeedViewEnabled(false), @@ -176,7 +189,7 @@ DocumentDB::DocumentDB(const vespalib::string &baseDir, _lidSpaceCompactionHandlers(), _jobTrackers(), _calc(), - _metricsUpdater(_subDBs, _writeService, _jobTrackers, *_sessionManager, _writeFilter, _state) + _metricsUpdater(_subDBs, _writeService, _jobTrackers, *_sessionManager, _writeFilter) { assert(configSnapshot); @@ -222,8 +235,7 @@ void DocumentDB::registerReference() } } -void DocumentDB::setActiveConfig(const DocumentDBConfig::SP &config, - SerialNum serialNum, int64_t generation) { +void DocumentDB::setActiveConfig(const DocumentDBConfig::SP &config, int64_t generation) { lock_guard guard(_configMutex); registerReference(); _activeConfigSnapshot = config; @@ -231,7 +243,6 @@ void DocumentDB::setActiveConfig(const DocumentDBConfig::SP &config, if (_activeConfigSnapshotGeneration < generation) { _activeConfigSnapshotGeneration = generation; } - _activeConfigSnapshotSerialNum = serialNum; _configCV.notify_all(); } @@ -297,7 +308,7 @@ DocumentDB::initFinish(DocumentDBConfig::SP configSnapshot) syncFeedView(); // Check that feed view has been activated. assert(_feedView.get()); - setActiveConfig(configSnapshot, _initConfigSerialNum, configSnapshot->getGeneration()); + setActiveConfig(configSnapshot, configSnapshot->getGeneration()); startTransactionLogReplay(); } @@ -469,7 +480,7 @@ DocumentDB::applyConfig(DocumentDBConfig::SP configSnapshot, SerialNum serialNum } _state.clearDelayedConfig(); } - setActiveConfig(configSnapshot, serialNum, generation); + setActiveConfig(configSnapshot, generation); if (params.shouldMaintenanceControllerChange()) { forwardMaintenanceConfig(); } @@ -1042,12 +1053,12 @@ DocumentDB::notifyAllBucketsChanged() } void -DocumentDB::updateMetrics(DocumentDBTaggedMetrics &metrics) +DocumentDB::updateMetrics(const metrics::MetricLockGuard & guard) { if (_state.getState() < DDBState::State::REPLAY_TRANSACTION_LOG) { return; } - _metricsUpdater.updateMetrics(metrics); + _metricsUpdater.updateMetrics(guard, _metrics); } void diff --git a/searchcore/src/vespa/searchcore/proton/server/documentdb.h b/searchcore/src/vespa/searchcore/proton/server/documentdb.h index a171861b590..9ea88360b07 100644 --- a/searchcore/src/vespa/searchcore/proton/server/documentdb.h +++ b/searchcore/src/vespa/searchcore/proton/server/documentdb.h @@ -18,7 +18,6 @@ #include "ireplayconfig.h" #include "maintenancecontroller.h" #include "threading_service_config.h" -#include <vespa/metrics/updatehook.h> #include <vespa/searchcore/proton/attribute/attribute_usage_filter.h> #include <vespa/searchcore/proton/common/doctypename.h> #include <vespa/searchcore/proton/common/monitored_refcount.h> @@ -42,6 +41,10 @@ namespace search { } namespace vespa::config::search::core::internal { class InternalProtonType; } +namespace metrics { + class UpdateHook; + class MetricLockGuard; +} namespace proton { class AttributeConfigInspector; @@ -68,26 +71,6 @@ class DocumentDB : public DocumentDBConfigOwner, public search::transactionlog::SyncProxy { private: - class MetricsUpdateHook : public metrics::UpdateHook { - DocumentDBTaggedMetrics _metrics; - DocumentDB &_db; - public: - MetricsUpdateHook(DocumentDB &s, const std::string &doc_type, size_t maxNumThreads) - : metrics::UpdateHook("documentdb-hook"), - _metrics(doc_type, maxNumThreads), - _db(s) {} - void updateMetrics(const MetricLockGuard & ) override { _db.updateMetrics(_metrics); } - DocumentDBTaggedMetrics &getMetrics() { return _metrics; } - }; - - struct DocumentStoreCacheStats { - search::CacheStats total; - search::CacheStats readySubDb; - search::CacheStats notReadySubDb; - search::CacheStats removedSubDb; - DocumentStoreCacheStats() : total(), readySubDb(), notReadySubDb(), removedSubDb() {} - }; - using InitializeThreads = std::shared_ptr<vespalib::SyncableThreadExecutor>; using IFlushTargetList = std::vector<std::shared_ptr<searchcorespi::IFlushTarget>>; using StatusReportUP = std::unique_ptr<StatusReport>; @@ -114,7 +97,6 @@ private: mutable std::condition_variable _configCV; DocumentDBConfig::SP _activeConfigSnapshot; int64_t _activeConfigSnapshotGeneration; - SerialNum _activeConfigSnapshotSerialNum; const bool _validateAndSanitizeDocStore; vespalib::Gate _initGate; @@ -126,9 +108,10 @@ private: index::IndexConfig _indexCfg; ConfigStore::UP _config_store; std::shared_ptr<matching::SessionManager> _sessionManager; // TODO: This should not have to be a shared pointer. - MetricsWireService &_metricsWireService; - MetricsUpdateHook _metricsHook; - vespalib::VarHolder<IFeedView::SP> _feedView; + MetricsWireService &_metricsWireService; + DocumentDBTaggedMetrics _metrics; + std::unique_ptr<metrics::UpdateHook> _metricsHook; + vespalib::VarHolder<IFeedView::SP> _feedView; MonitoredRefCount _refCount; bool _syncFeedViewEnabled; IDocumentDBOwner &_owner; @@ -145,7 +128,7 @@ private: DocumentDBMetricsUpdater _metricsUpdater; void registerReference(); - void setActiveConfig(const DocumentDBConfig::SP &config, SerialNum serialNum, int64_t generation); + void setActiveConfig(const DocumentDBConfig::SP &config, int64_t generation); DocumentDBConfig::SP getActiveConfig() const; void internalInit(); void initManagers(); @@ -294,7 +277,9 @@ public: * * @return document db metrics **/ - DocumentDBTaggedMetrics &getMetrics() { return _metricsHook.getMetrics(); } + DocumentDBTaggedMetrics &getMetrics() { + return _metrics; + } /** * Obtain the metrics update hook for this document db. @@ -302,7 +287,7 @@ public: * @return metrics update hook **/ metrics::UpdateHook & getMetricsUpdateHook() { - return _metricsHook; + return *_metricsHook; } /** @@ -414,7 +399,7 @@ public: * the metric manager). Do not call this function in multiple * threads at once. **/ - void updateMetrics(DocumentDBTaggedMetrics &metrics); + void updateMetrics(const metrics::MetricLockGuard & guard); /** * Implement search::transactionlog::SyncProxy API. diff --git a/searchcore/src/vespa/searchcore/proton/server/documentdb_metrics_updater.cpp b/searchcore/src/vespa/searchcore/proton/server/documentdb_metrics_updater.cpp index 3a086046a27..8b923c7a372 100644 --- a/searchcore/src/vespa/searchcore/proton/server/documentdb_metrics_updater.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/documentdb_metrics_updater.cpp @@ -34,8 +34,7 @@ DocumentDBMetricsUpdater::DocumentDBMetricsUpdater(const DocumentSubDBCollection ExecutorThreadingService &writeService, DocumentDBJobTrackers &jobTrackers, matching::SessionManager &sessionManager, - const AttributeUsageFilter &writeFilter, - [[maybe_unused]] const DDBState &state) + const AttributeUsageFilter &writeFilter) : _subDBs(subDBs), _writeService(writeService), _jobTrackers(jobTrackers), @@ -170,12 +169,12 @@ updateAttributeMetrics(DocumentDBTaggedMetrics &metrics, const DocumentSubDBColl } void -updateMatchingMetrics(DocumentDBTaggedMetrics &metrics, const IDocumentSubDB &ready) +updateMatchingMetrics(const metrics::MetricLockGuard & guard, DocumentDBTaggedMetrics &metrics, const IDocumentSubDB &ready) { MatchingStats totalStats; for (const auto &rankProfile : metrics.matching.rank_profiles) { MatchingStats matchingStats = ready.getMatcherStats(rankProfile.first); - rankProfile.second->update(matchingStats); + rankProfile.second->update(guard, matchingStats); totalStats.add(matchingStats); } @@ -284,13 +283,13 @@ updateLidSpaceMetrics(MetricSetType &metrics, const search::IDocumentMetaStore & } void -DocumentDBMetricsUpdater::updateMetrics(DocumentDBTaggedMetrics &metrics) +DocumentDBMetricsUpdater::updateMetrics(const metrics::MetricLockGuard & guard, DocumentDBTaggedMetrics &metrics) { TotalStats totalStats; ExecutorThreadingServiceStats threadingServiceStats = _writeService.getStats(); updateIndexMetrics(metrics, _subDBs.getReadySubDB()->getSearchableStats(), totalStats); updateAttributeMetrics(metrics, _subDBs, totalStats); - updateMatchingMetrics(metrics, *_subDBs.getReadySubDB()); + updateMatchingMetrics(guard, metrics, *_subDBs.getReadySubDB()); updateSessionCacheMetrics(metrics, _sessionManager); updateDocumentsMetrics(metrics, _subDBs); updateDocumentStoreMetrics(metrics, _subDBs, _lastDocStoreCacheStats, totalStats); diff --git a/searchcore/src/vespa/searchcore/proton/server/documentdb_metrics_updater.h b/searchcore/src/vespa/searchcore/proton/server/documentdb_metrics_updater.h index dbf4c45007f..475da7f4e4c 100644 --- a/searchcore/src/vespa/searchcore/proton/server/documentdb_metrics_updater.h +++ b/searchcore/src/vespa/searchcore/proton/server/documentdb_metrics_updater.h @@ -45,11 +45,10 @@ public: ExecutorThreadingService &writeService, DocumentDBJobTrackers &jobTrackers, matching::SessionManager &sessionManager, - const AttributeUsageFilter &writeFilter, - const DDBState &state); + const AttributeUsageFilter &writeFilter); ~DocumentDBMetricsUpdater(); - void updateMetrics(DocumentDBTaggedMetrics &metrics); + void updateMetrics(const metrics::MetricLockGuard & guard, DocumentDBTaggedMetrics &metrics); }; diff --git a/searchcore/src/vespa/searchcore/proton/server/executor_explorer_utils.cpp b/searchcore/src/vespa/searchcore/proton/server/executor_explorer_utils.cpp new file mode 100644 index 00000000000..bbb87099988 --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/server/executor_explorer_utils.cpp @@ -0,0 +1,57 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "executor_explorer_utils.h" +#include <vespa/vespalib/data/slime/cursor.h> +#include <vespa/vespalib/util/blockingthreadstackexecutor.h> +#include <vespa/vespalib/util/singleexecutor.h> +#include <vespa/vespalib/util/threadexecutor.h> +#include <vespa/vespalib/util/threadstackexecutor.h> + +using vespalib::BlockingThreadStackExecutor; +using vespalib::SingleExecutor; +using vespalib::SyncableThreadExecutor; +using vespalib::ThreadStackExecutor; +using vespalib::slime::Cursor; + + +namespace proton::explorer { + +namespace { + +void +convert_syncable_executor_to_slime(const SyncableThreadExecutor& executor, const vespalib::string& type, Cursor& object) +{ + object.setString("type", type); + object.setLong("num_threads", executor.getNumThreads()); + object.setLong("task_limit", executor.getTaskLimit()); +} + +void +convert_single_executor_to_slime(const SingleExecutor& executor, Cursor& object) +{ + convert_syncable_executor_to_slime(executor, "SingleExecutor", object); + object.setLong("watermark", executor.get_watermark()); + object.setDouble("reaction_time_sec", vespalib::to_s(executor.get_reaction_time())); +} + +} + +void +convert_executor_to_slime(const SyncableThreadExecutor* executor, Cursor& object) +{ + if (executor == nullptr) { + return; + } + if (const auto* single = dynamic_cast<const SingleExecutor*>(executor)) { + convert_single_executor_to_slime(*single, object); + } else if (const auto* blocking = dynamic_cast<const BlockingThreadStackExecutor*>(executor)) { + convert_syncable_executor_to_slime(*blocking, "BlockingThreadStackExecutor", object); + } else if (const auto* thread = dynamic_cast<const ThreadStackExecutor*>(executor)) { + convert_syncable_executor_to_slime(*thread, "ThreadStackExecutor", object); + } else { + convert_syncable_executor_to_slime(*executor, "SyncableThreadExecutor", object); + } +} + +} + diff --git a/searchcore/src/vespa/searchcore/proton/server/executor_explorer_utils.h b/searchcore/src/vespa/searchcore/proton/server/executor_explorer_utils.h new file mode 100644 index 00000000000..0793fa6ac4a --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/server/executor_explorer_utils.h @@ -0,0 +1,16 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +namespace vespalib { class SyncableThreadExecutor; } +namespace vespalib::slime { struct Cursor; } + +namespace proton::explorer { + +/** + * Utility to convert an executor to slime for use with a state explorer. + */ +void convert_executor_to_slime(const vespalib::SyncableThreadExecutor* executor, vespalib::slime::Cursor& object); + +} + diff --git a/searchcore/src/vespa/searchcore/proton/server/executor_threading_service_explorer.cpp b/searchcore/src/vespa/searchcore/proton/server/executor_threading_service_explorer.cpp index 0ecdca54e27..e3154ad6a47 100644 --- a/searchcore/src/vespa/searchcore/proton/server/executor_threading_service_explorer.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/executor_threading_service_explorer.cpp @@ -1,26 +1,21 @@ // Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include "executor_explorer_utils.h" #include "executor_threading_service_explorer.h" #include "executorthreadingservice.h" #include <vespa/vespalib/data/slime/cursor.h> #include <vespa/vespalib/util/adaptive_sequenced_executor.h> -#include <vespa/vespalib/util/blockingthreadstackexecutor.h> #include <vespa/vespalib/util/sequencedtaskexecutor.h> -#include <vespa/vespalib/util/singleexecutor.h> -#include <vespa/vespalib/util/threadexecutor.h> -#include <vespa/vespalib/util/threadstackexecutor.h> using vespalib::AdaptiveSequencedExecutor; -using vespalib::BlockingThreadStackExecutor; using vespalib::ISequencedTaskExecutor; using vespalib::SequencedTaskExecutor; -using vespalib::SingleExecutor; -using vespalib::SyncableThreadExecutor; -using vespalib::ThreadStackExecutor; using vespalib::slime::Cursor; namespace proton { +using explorer::convert_executor_to_slime; + namespace { void @@ -30,39 +25,6 @@ set_type(Cursor& object, const vespalib::string& type) } void -convert_syncable_executor_to_slime(const SyncableThreadExecutor& executor, const vespalib::string& type, Cursor& object) -{ - set_type(object, type); - object.setLong("num_threads", executor.getNumThreads()); - object.setLong("task_limit", executor.getTaskLimit()); -} - -void -convert_single_executor_to_slime(const SingleExecutor& executor, Cursor& object) -{ - convert_syncable_executor_to_slime(executor, "SingleExecutor", object); - object.setLong("watermark", executor.get_watermark()); - object.setDouble("reaction_time_sec", vespalib::to_s(executor.get_reaction_time())); -} - -void -convert_executor_to_slime(const SyncableThreadExecutor* executor, Cursor& object) -{ - if (executor == nullptr) { - return; - } - if (const auto* single = dynamic_cast<const SingleExecutor*>(executor)) { - convert_single_executor_to_slime(*single, object); - } else if (const auto* blocking = dynamic_cast<const BlockingThreadStackExecutor*>(executor)) { - convert_syncable_executor_to_slime(*blocking, "BlockingThreadStackExecutor", object); - } else if (const auto* thread = dynamic_cast<const ThreadStackExecutor*>(executor)) { - convert_syncable_executor_to_slime(*thread, "ThreadStackExecutor", object); - } else { - convert_syncable_executor_to_slime(*executor, "SyncableThreadExecutor", object); - } -} - -void convert_sequenced_executor_to_slime(const SequencedTaskExecutor& executor, Cursor& object) { set_type(object, "SequencedTaskExecutor"); diff --git a/searchcore/src/vespa/searchcore/proton/server/proton.cpp b/searchcore/src/vespa/searchcore/proton/server/proton.cpp index dddca6a9ddd..36d630bc519 100644 --- a/searchcore/src/vespa/searchcore/proton/server/proton.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/proton.cpp @@ -10,6 +10,7 @@ #include "proton.h" #include "proton_config_snapshot.h" #include "proton_disk_layout.h" +#include "proton_thread_pools_explorer.h" #include "resource_usage_explorer.h" #include "searchhandlerproxy.h" #include "simpleflush.h" @@ -34,6 +35,7 @@ #include <vespa/vespalib/util/host_name.h> #include <vespa/vespalib/util/lambdatask.h> #include <vespa/vespalib/util/random.h> +#include <vespa/metrics/updatehook.h> #include <vespa/searchlib/aggregation/forcelink.hpp> #include <vespa/searchlib/expression/forcelink.hpp> @@ -112,6 +114,18 @@ derive_shared_threads(const ProtonConfig &proton, return std::max(scaledCores, proton.documentdb.size() + proton.flush.maxconcurrent + 1); } +struct MetricsUpdateHook : metrics::UpdateHook +{ + Proton &self; + MetricsUpdateHook(Proton &s) + : metrics::UpdateHook("proton-hook"), + self(s) + {} + void updateMetrics(const MetricLockGuard &guard) override { + self.updateMetrics(guard); + } +}; + const vespalib::string CUSTOM_COMPONENT_API_PATH = "/state/v1/custom/component"; VESPA_THREAD_STACK_TAG(proton_shared_executor) @@ -121,7 +135,7 @@ VESPA_THREAD_STACK_TAG(close_executor) } -Proton::ProtonFileHeaderContext::ProtonFileHeaderContext([[maybe_unused]] const Proton &proton_, const vespalib::string &creator) +Proton::ProtonFileHeaderContext::ProtonFileHeaderContext(const vespalib::string &creator) : _hostName(), _creator(creator), _cluster(), @@ -186,9 +200,9 @@ Proton::Proton(const config::ConfigUri & configUri, ComponentConfigProducer(), _configUri(configUri), _mutex(), - _metricsHook(*this), + _metricsHook(std::make_unique<MetricsUpdateHook>(*this)), _metricsEngine(std::make_unique<MetricsEngine>()), - _fileHeaderContext(*this, progName), + _fileHeaderContext(progName), _tls(), _diskMemUsageSampler(), _persistenceEngine(), @@ -219,7 +233,6 @@ Proton::Proton(const config::ConfigUri & configUri, _threadPool(128 * 1024), _distributionKey(-1), _isInitializing(true), - _isReplayDone(false), _abortInit(false), _initStarted(false), _initComplete(false), @@ -260,7 +273,7 @@ Proton::init(const BootstrapConfig::SP & configSnapshot) diskMemUsageSamplerConfig(protonConfig, hwInfo)); _tls = std::make_unique<TLS>(_configUri.createWithNewId(protonConfig.tlsconfigid), _fileHeaderContext); - _metricsEngine->addMetricsHook(_metricsHook); + _metricsEngine->addMetricsHook(*_metricsHook); _fileHeaderContext.setClusterName(protonConfig.clustername, protonConfig.basedir); _matchEngine = std::make_unique<MatchEngine>(protonConfig.numsearcherthreads, protonConfig.numthreadspersearch, @@ -331,7 +344,6 @@ Proton::init(const BootstrapConfig::SP & configSnapshot) _executor.sync(); waitForOnlineState(); - _isReplayDone = true; _rpcHooks->set_online(); _flushEngine->start(); @@ -470,7 +482,7 @@ Proton::shutdown_config_fetching_and_state_exposing_components_once() noexcept _customComponentBindToken.reset(); _stateServer.reset(); if (_metricsEngine) { - _metricsEngine->removeMetricsHook(_metricsHook); + _metricsEngine->removeMetricsHook(*_metricsHook); _metricsEngine->stop(); } _has_shut_down_config_and_state_components = true; @@ -714,7 +726,7 @@ updateExecutorMetrics(ExecutorMetrics &metrics, } void -Proton::updateMetrics(const metrics::UpdateHook::MetricLockGuard &) +Proton::updateMetrics(const metrics::MetricLockGuard &) { { ContentProtonMetrics &metrics = _metricsEngine->root(); @@ -836,6 +848,7 @@ const vespalib::string DOCUMENT_DB = "documentdb"; const vespalib::string FLUSH_ENGINE = "flushengine"; const vespalib::string TLS_NAME = "tls"; const vespalib::string RESOURCE_USAGE = "resourceusage"; +const vespalib::string THREAD_POOLS = "threadpools"; struct StateExplorerProxy : vespalib::StateExplorer { const StateExplorer &explorer; @@ -881,8 +894,7 @@ Proton::get_state(const vespalib::slime::Inserter &, bool) const std::vector<vespalib::string> Proton::get_children_names() const { - std::vector<vespalib::string> names({DOCUMENT_DB, MATCH_ENGINE, FLUSH_ENGINE, TLS_NAME, RESOURCE_USAGE}); - return names; + return {DOCUMENT_DB, THREAD_POOLS, MATCH_ENGINE, FLUSH_ENGINE, TLS_NAME, RESOURCE_USAGE}; } std::unique_ptr<vespalib::StateExplorer> @@ -899,6 +911,13 @@ Proton::get_child(vespalib::stringref name) const return std::make_unique<search::transactionlog::TransLogServerExplorer>(_tls->getTransLogServer()); } else if (name == RESOURCE_USAGE && _diskMemUsageSampler) { return std::make_unique<ResourceUsageExplorer>(_diskMemUsageSampler->writeFilter()); + } else if (name == THREAD_POOLS) { + return std::make_unique<ProtonThreadPoolsExplorer>(_sharedExecutor.get(), + (_matchEngine) ? &_matchEngine->get_executor() : nullptr, + (_summaryEngine) ? &_summaryEngine->get_executor() : nullptr, + (_flushEngine) ? &_flushEngine->get_executor() : nullptr, + &_executor, + _warmupExecutor.get()); } return Explorer_UP(nullptr); } diff --git a/searchcore/src/vespa/searchcore/proton/server/proton.h b/searchcore/src/vespa/searchcore/proton/server/proton.h index f88cd7bf0cd..2241389a63c 100644 --- a/searchcore/src/vespa/searchcore/proton/server/proton.h +++ b/searchcore/src/vespa/searchcore/proton/server/proton.h @@ -31,6 +31,7 @@ namespace vespalib { class StateServer; } namespace search::transactionlog { class TransLogServerApp; } +namespace metrics { class MetricLockGuard; } namespace proton { class DiskMemUsageSampler; @@ -60,16 +61,6 @@ private: using InitializeThreads = std::shared_ptr<vespalib::SyncableThreadExecutor>; using BucketSpace = document::BucketSpace; - struct MetricsUpdateHook : metrics::UpdateHook - { - Proton &self; - MetricsUpdateHook(Proton &s) - : metrics::UpdateHook("proton-hook"), - self(s) {} - void updateMetrics(const MetricLockGuard &guard) override { self.updateMetrics(guard); } - }; - friend struct MetricsUpdateHook; - class ProtonFileHeaderContext : public search::common::FileHeaderContext { vespalib::string _hostName; @@ -78,23 +69,23 @@ private: pid_t _pid; public: - ProtonFileHeaderContext(const Proton &proton_, const vespalib::string &creator); + ProtonFileHeaderContext(const vespalib::string &creator); ~ProtonFileHeaderContext() override; void addTags(vespalib::GenericHeader &header, const vespalib::string &name) const override; void setClusterName(const vespalib::string &clusterName, const vespalib::string &baseDir); }; - const config::ConfigUri _configUri; - mutable std::shared_mutex _mutex; - MetricsUpdateHook _metricsHook; - std::unique_ptr<MetricsEngine> _metricsEngine; - ProtonFileHeaderContext _fileHeaderContext; - std::unique_ptr<TLS> _tls; + const config::ConfigUri _configUri; + mutable std::shared_mutex _mutex; + std::unique_ptr<metrics::UpdateHook> _metricsHook; + std::unique_ptr<MetricsEngine> _metricsEngine; + ProtonFileHeaderContext _fileHeaderContext; + std::unique_ptr<TLS> _tls; std::unique_ptr<DiskMemUsageSampler> _diskMemUsageSampler; PersistenceEngine::UP _persistenceEngine; DocumentDBMap _documentDBMap; - std::unique_ptr<MatchEngine> _matchEngine; + std::unique_ptr<MatchEngine> _matchEngine; std::unique_ptr<SummaryEngine> _summaryEngine; std::unique_ptr<DocsumBySlime> _docsumBySlime; MemoryFlushConfigUpdater::UP _memoryFlushConfigUpdater; @@ -138,12 +129,6 @@ private: void applyConfig(const BootstrapConfig::SP & configSnapshot) override; MonitorReply::UP ping(MonitorRequest::UP request, MonitorClient &client) override; - /** - * Called by the metrics update hook (typically in the context of - * the metric manager). Do not call this function in multiple - * threads at once. - **/ - void updateMetrics(const metrics::UpdateHook::MetricLockGuard &guard); void waitForInitDone(); void waitForOnlineState(); uint32_t getDistributionKey() const override { return _distributionKey; } @@ -161,6 +146,13 @@ public: ~Proton() override; /** + * Called by the metrics update hook (typically in the context of + * the metric manager). Do not call this function in multiple + * threads at once. + **/ + void updateMetrics(const metrics::MetricLockGuard &guard); + + /** * This method must be called after the constructor and before the destructor. * If not I will force a 'core' upon you. * All relevant initialization is conducted here. diff --git a/searchcore/src/vespa/searchcore/proton/server/proton_thread_pools_explorer.cpp b/searchcore/src/vespa/searchcore/proton/server/proton_thread_pools_explorer.cpp new file mode 100644 index 00000000000..e0db9e29c35 --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/server/proton_thread_pools_explorer.cpp @@ -0,0 +1,43 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#include "executor_explorer_utils.h" +#include "proton_thread_pools_explorer.h" +#include <vespa/vespalib/data/slime/cursor.h> +#include <vespa/vespalib/util/threadexecutor.h> + +using vespalib::SyncableThreadExecutor; + +namespace proton { + +using explorer::convert_executor_to_slime; + +ProtonThreadPoolsExplorer::ProtonThreadPoolsExplorer(const SyncableThreadExecutor* shared, + const SyncableThreadExecutor* match, + const SyncableThreadExecutor* docsum, + const SyncableThreadExecutor* flush, + const SyncableThreadExecutor* proton, + const SyncableThreadExecutor* warmup) + : _shared(shared), + _match(match), + _docsum(docsum), + _flush(flush), + _proton(proton), + _warmup(warmup) +{ +} + +void +ProtonThreadPoolsExplorer::get_state(const vespalib::slime::Inserter& inserter, bool full) const +{ + auto& object = inserter.insertObject(); + if (full) { + convert_executor_to_slime(_shared, object.setObject("shared")); + convert_executor_to_slime(_match, object.setObject("match")); + convert_executor_to_slime(_docsum, object.setObject("docsum")); + convert_executor_to_slime(_flush, object.setObject("flush")); + convert_executor_to_slime(_proton, object.setObject("proton")); + convert_executor_to_slime(_warmup, object.setObject("warmup")); + } +} + +} diff --git a/searchcore/src/vespa/searchcore/proton/server/proton_thread_pools_explorer.h b/searchcore/src/vespa/searchcore/proton/server/proton_thread_pools_explorer.h new file mode 100644 index 00000000000..8022a0483c4 --- /dev/null +++ b/searchcore/src/vespa/searchcore/proton/server/proton_thread_pools_explorer.h @@ -0,0 +1,35 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include <vespa/vespalib/net/state_explorer.h> + +namespace vespalib { class SyncableThreadExecutor; } + +namespace proton { + +/** + * Class used to explore the shared thread pools used by proton and it's document databases. + */ +class ProtonThreadPoolsExplorer : public vespalib::StateExplorer { +private: + const vespalib::SyncableThreadExecutor* _shared; + const vespalib::SyncableThreadExecutor* _match; + const vespalib::SyncableThreadExecutor* _docsum; + const vespalib::SyncableThreadExecutor* _flush; + const vespalib::SyncableThreadExecutor* _proton; + const vespalib::SyncableThreadExecutor* _warmup; + +public: + ProtonThreadPoolsExplorer(const vespalib::SyncableThreadExecutor* shared, + const vespalib::SyncableThreadExecutor* match, + const vespalib::SyncableThreadExecutor* docsum, + const vespalib::SyncableThreadExecutor* flush, + const vespalib::SyncableThreadExecutor* proton, + const vespalib::SyncableThreadExecutor* warmup); + + void get_state(const vespalib::slime::Inserter& inserter, bool full) const override; +}; + +} + diff --git a/searchcore/src/vespa/searchcore/proton/server/storeonlydocsubdb.cpp b/searchcore/src/vespa/searchcore/proton/server/storeonlydocsubdb.cpp index 7d5d49b19c7..0bd50fc0104 100644 --- a/searchcore/src/vespa/searchcore/proton/server/storeonlydocsubdb.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/storeonlydocsubdb.cpp @@ -120,7 +120,7 @@ StoreOnlyDocSubDB::StoreOnlyDocSubDB(const Config &cfg, const Context &ctx) _pendingLidsForCommit(std::make_shared<PendingLidTracker>()), _subDbId(cfg._subDbId), _subDbType(cfg._subDbType), - _fileHeaderContext(*this, ctx._fileHeaderContext, _docTypeName, _baseDir), + _fileHeaderContext(ctx._fileHeaderContext, _docTypeName, _baseDir), _gidToLidChangeHandler(std::make_shared<DummyGidToLidChangeHandler>()) { vespalib::mkdir(_baseDir, false); // Assume parent is created. @@ -497,8 +497,7 @@ StoreOnlyDocSubDB::getDocumentDBReference() } StoreOnlySubDBFileHeaderContext:: -StoreOnlySubDBFileHeaderContext([[maybe_unused]] StoreOnlyDocSubDB &owner, - const FileHeaderContext & parentFileHeaderContext, +StoreOnlySubDBFileHeaderContext(const FileHeaderContext & parentFileHeaderContext, const DocTypeName &docTypeName, const vespalib::string &baseDir) : FileHeaderContext(), diff --git a/searchcore/src/vespa/searchcore/proton/server/storeonlydocsubdb.h b/searchcore/src/vespa/searchcore/proton/server/storeonlydocsubdb.h index 1cdd22fcc41..7c3f7c82eb0 100644 --- a/searchcore/src/vespa/searchcore/proton/server/storeonlydocsubdb.h +++ b/searchcore/src/vespa/searchcore/proton/server/storeonlydocsubdb.h @@ -50,8 +50,6 @@ public: void close() override { } }; -class StoreOnlyDocSubDB; - /** * File header context used by the store-only sub database. * @@ -65,8 +63,7 @@ class StoreOnlySubDBFileHeaderContext : public search::common::FileHeaderContext vespalib::string _subDB; public: - StoreOnlySubDBFileHeaderContext(StoreOnlyDocSubDB &owner, - const search::common::FileHeaderContext & parentFileHeaderContext, + StoreOnlySubDBFileHeaderContext(const search::common::FileHeaderContext & parentFileHeaderContext, const DocTypeName &docTypeName, const vespalib::string &baseDir); ~StoreOnlySubDBFileHeaderContext(); diff --git a/searchcore/src/vespa/searchcore/proton/summaryengine/summaryengine.h b/searchcore/src/vespa/searchcore/proton/summaryengine/summaryengine.h index 029aefacfc8..c1cb1f91a2a 100644 --- a/searchcore/src/vespa/searchcore/proton/summaryengine/summaryengine.h +++ b/searchcore/src/vespa/searchcore/proton/summaryengine/summaryengine.h @@ -65,6 +65,11 @@ public: vespalib::ThreadStackExecutor::Stats getExecutorStats() { return _executor.getStats(); } /** + * Returns the underlying executor. Only used for state explorers. + */ + const vespalib::SyncableThreadExecutor& get_executor() const { return _executor; } + + /** * Starts the underlying threads. This will throw a vespalib::Exception if * it failed to start for any reason. */ |