diff options
author | Henrik Edin <henrik.edin@mongodb.com> | 2021-09-27 18:50:00 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-09-27 19:15:10 +0000 |
commit | f39e5fd6735431e899f1fc1689184f63b4b461ae (patch) | |
tree | f7faf02fe44d11ede2b7e38749875376a2ee0a5f /src/mongo/db | |
parent | 4ea51acda7d7659cb75dfdc6ed463bc5104c8238 (diff) | |
download | mongo-f39e5fd6735431e899f1fc1689184f63b4b461ae.tar.gz |
SERVER-60087 Add stats under collStats for timeseries bucket compression
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/commands/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/commands/write_commands.cpp | 34 | ||||
-rw-r--r-- | src/mongo/db/stats/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/stats/storage_stats.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/timeseries/SConscript | 10 | ||||
-rw-r--r-- | src/mongo/db/timeseries/timeseries_stats.cpp | 65 | ||||
-rw-r--r-- | src/mongo/db/timeseries/timeseries_stats.h | 66 |
7 files changed, 172 insertions, 7 deletions
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript index fde798457c6..4d75bf91168 100644 --- a/src/mongo/db/commands/SConscript +++ b/src/mongo/db/commands/SConscript @@ -368,6 +368,7 @@ env.Library( '$BUILD_DIR/mongo/db/timeseries/catalog_helper', '$BUILD_DIR/mongo/db/timeseries/timeseries_conversion_util', '$BUILD_DIR/mongo/db/timeseries/timeseries_options', + '$BUILD_DIR/mongo/db/timeseries/timeseries_stats', '$BUILD_DIR/mongo/db/transaction', '$BUILD_DIR/mongo/db/views/views_mongod', '$BUILD_DIR/mongo/executor/async_request_executor', diff --git a/src/mongo/db/commands/write_commands.cpp b/src/mongo/db/commands/write_commands.cpp index 9452f0c74b3..61f6b31d0a0 100644 --- a/src/mongo/db/commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands.cpp @@ -69,6 +69,7 @@ #include "mongo/db/timeseries/bucket_catalog.h" #include "mongo/db/timeseries/bucket_compression.h" #include "mongo/db/timeseries/timeseries_constants.h" +#include "mongo/db/timeseries/timeseries_stats.h" #include "mongo/db/transaction_participant.h" #include "mongo/db/views/view_catalog.h" #include "mongo/db/write_concern.h" @@ -690,11 +691,16 @@ public: return SingleWriteResult(); } - auto bucketCompressionFunc = - [&closedBucket](const BSONObj& bucketDoc) -> boost::optional<BSONObj> { + boost::optional<int> beforeSize; + boost::optional<int> afterSize; + + auto bucketCompressionFunc = [&](const BSONObj& bucketDoc) -> boost::optional<BSONObj> { + beforeSize = bucketDoc.objsize(); + // Reset every time we run to ensure we never use a stale value + afterSize = boost::none; auto compressed = timeseries::compressBucket(bucketDoc, closedBucket.timeField); // If compressed object size is larger than uncompressed, skip compression update. - if (compressed && compressed->objsize() > bucketDoc.objsize()) { + if (compressed && compressed->objsize() >= *beforeSize) { LOGV2_DEBUG(5857802, 1, "Skipping time-series bucket compression, compressed object is " @@ -703,13 +709,27 @@ public: "compressedSize"_attr = compressed->objsize()); return boost::none; } + afterSize = compressed->objsize(); return compressed; }; - return _getTimeseriesSingleWriteResult(write_ops_exec::performUpdates( - opCtx, - _makeTimeseriesCompressionOp(opCtx, closedBucket.bucketId, bucketCompressionFunc), - OperationSource::kStandard)); + auto compressionOp = + _makeTimeseriesCompressionOp(opCtx, closedBucket.bucketId, bucketCompressionFunc); + auto result = _getTimeseriesSingleWriteResult( + write_ops_exec::performUpdates(opCtx, compressionOp, OperationSource::kStandard)); + + // Report stats, if we fail before running the transform function then just skip + // reporting. + if (result.isOK() && beforeSize) { + auto coll = CollectionCatalog::get(opCtx)->lookupCollectionByNamespaceForRead( + opCtx, compressionOp.getNamespace()); + if (coll) { + const auto& stats = TimeseriesStats::get(coll.get()); + stats.onBucketClosed(*beforeSize, afterSize); + } + } + + return result; } void _commitTimeseriesBucket(OperationContext* opCtx, diff --git a/src/mongo/db/stats/SConscript b/src/mongo/db/stats/SConscript index d7a439cd38e..b27a81181ac 100644 --- a/src/mongo/db/stats/SConscript +++ b/src/mongo/db/stats/SConscript @@ -129,6 +129,7 @@ env.Library( '$BUILD_DIR/mongo/db/index/index_access_method', '$BUILD_DIR/mongo/db/pipeline/document_sources_idl', '$BUILD_DIR/mongo/db/timeseries/bucket_catalog', + '$BUILD_DIR/mongo/db/timeseries/timeseries_stats', 'fill_locker_info', 'top', ], diff --git a/src/mongo/db/stats/storage_stats.cpp b/src/mongo/db/stats/storage_stats.cpp index 96067384f6a..a2253d49706 100644 --- a/src/mongo/db/stats/storage_stats.cpp +++ b/src/mongo/db/stats/storage_stats.cpp @@ -38,6 +38,7 @@ #include "mongo/db/index/index_access_method.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/timeseries/bucket_catalog.h" +#include "mongo/db/timeseries/timeseries_stats.h" #include "mongo/db/views/view_catalog.h" #include "mongo/logv2/log.h" @@ -99,6 +100,7 @@ Status appendCollectionStorageStats(OperationContext* opCtx, bob.append("avgBucketSize", collection->averageObjectSize(opCtx)); } BucketCatalog::get(opCtx).appendExecutionStats(collNss.getTimeseriesViewNamespace(), &bob); + TimeseriesStats::get(collection.get()).append(&bob); } else { result->appendNumber("count", numRecords); if (numRecords) { diff --git a/src/mongo/db/timeseries/SConscript b/src/mongo/db/timeseries/SConscript index 2a5ac31b204..e8b0f135c81 100644 --- a/src/mongo/db/timeseries/SConscript +++ b/src/mongo/db/timeseries/SConscript @@ -47,6 +47,16 @@ env.Library( ) env.Library( + target='timeseries_stats', + source=[ + 'timeseries_stats.cpp', + ], + LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/base', + ], +) + +env.Library( target='catalog_helper', source=[ 'catalog_helper.cpp', diff --git a/src/mongo/db/timeseries/timeseries_stats.cpp b/src/mongo/db/timeseries/timeseries_stats.cpp new file mode 100644 index 00000000000..33cafb386ff --- /dev/null +++ b/src/mongo/db/timeseries/timeseries_stats.cpp @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2021-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/db/timeseries/timeseries_stats.h" + +#include "mongo/db/catalog/collection.h" + +namespace mongo { +namespace { + +const auto getTimeseriesStatsDecoration = + SharedCollectionDecorations::declareDecoration<TimeseriesStats>(); + +} // namespace + +const TimeseriesStats& TimeseriesStats::get(const Collection* coll) { + return getTimeseriesStatsDecoration(coll->getSharedDecorations()); +} + +void TimeseriesStats::onBucketClosed(int uncompressedSize, + boost::optional<int> compressedSize) const { + _uncompressedSize.fetchAndAddRelaxed(uncompressedSize); + if (compressedSize) { + _compressedSize.fetchAndAddRelaxed(*compressedSize); + _numCompressedBuckets.fetchAndAddRelaxed(1); + } else { + _compressedSize.fetchAndAddRelaxed(uncompressedSize); + _numUncompressedBuckets.fetchAndAddRelaxed(1); + } +} + +void TimeseriesStats::append(BSONObjBuilder* builder) const { + builder->appendNumber("numBytesUncompressed", _uncompressedSize.load()); + builder->appendNumber("numBytesCompressed", _compressedSize.load()); + builder->appendNumber("numCompressedBuckets", _numCompressedBuckets.load()); + builder->appendNumber("numUncompressedBuckets", _numUncompressedBuckets.load()); +} + +} // namespace mongo diff --git a/src/mongo/db/timeseries/timeseries_stats.h b/src/mongo/db/timeseries/timeseries_stats.h new file mode 100644 index 00000000000..c7870f34d35 --- /dev/null +++ b/src/mongo/db/timeseries/timeseries_stats.h @@ -0,0 +1,66 @@ +/** + * Copyright (C) 2021-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#pragma once + +#include <boost/optional.hpp> + +#include "mongo/db/catalog/collection.h" + +namespace mongo { +/** + * Timeseries statistics at Collection-level. Decorates 'SharedCollectionDecorations' and is not + * versioned per Collection instance. + * + * Used for timeseries statistics the BucketCatalog is unable to keep track of. + */ +class TimeseriesStats { +public: + static const TimeseriesStats& get(const Collection* coll); + + /** + * Records stats for a closed time-series bucket. 'boost::none' for compressedSize means + * compression failed for any reason. + */ + void onBucketClosed(int uncompressedSize, boost::optional<int> compressedSize) const; + + /** + * Appends current stats to the given BSONObjBuilder. + */ + void append(BSONObjBuilder* builder) const; + +private: + // We need to be able to record stats on a time-series bucket collection without requiring a + // non-const Collection (which requires MODE_X collection lock). + mutable AtomicWord<long long> _uncompressedSize; + mutable AtomicWord<long long> _compressedSize; + mutable AtomicWord<long long> _numCompressedBuckets; + mutable AtomicWord<long long> _numUncompressedBuckets; +}; +} // namespace mongo |