diff options
author | Øyvind Grønnesby <oyving@yahooinc.com> | 2023-03-14 13:48:27 +0100 |
---|---|---|
committer | Øyvind Grønnesby <oyving@yahooinc.com> | 2023-03-14 13:48:27 +0100 |
commit | 599d12f28ae624f99b19c61d1ede27121b3a4b54 (patch) | |
tree | 7efd999a5f74ad6c7b30fa0889791900ea9a4671 | |
parent | 82cd17263d69b9310fd52172faac560495fa052a (diff) | |
parent | 90691fbbd9db5aff6f698293968ad2f27a4f4db0 (diff) |
Merge remote-tracking branch 'origin/master' into ogronnesby/ignore-minor-micro
26 files changed, 155 insertions, 107 deletions
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java index c92715e5d4f..f3c214da6ec 100644 --- a/config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java +++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Capacity.java @@ -35,8 +35,6 @@ public final class Capacity { if (max.smallerThan(min)) throw new IllegalArgumentException("The max capacity must be larger than the min capacity, but got min " + min + " and max " + max); - if (!min.equals(max) && Stream.of(min, max).anyMatch(cr -> !cr.nodeResources().gpuResources().isZero())) - throw new IllegalArgumentException("Capacity range does not allow GPU, got min " + min + " and max " + max); this.min = min; this.max = max; this.groupSize = groupSize; diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java index 7df216d6c9c..28248560a6f 100644 --- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java +++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/controller/MeteringResponse.java @@ -26,13 +26,16 @@ public class MeteringResponse extends SlimeJsonResponse { List<ResourceSnapshot> snapshots = resourceClient.getRawSnapshotHistoryForTenant(TenantName.from(tenantName), YearMonth.parse(month)); snapshots.forEach(snapshot -> { Cursor object = root.addObject(); - object.setString("applicationId", snapshot.getApplicationId().toShortString()); + object.setString("applicationId", snapshot.getApplicationId().toFullString()); object.setLong("timestamp", snapshot.getTimestamp().toEpochMilli()); object.setString("zoneId", snapshot.getZoneId().value()); object.setDouble("cpu", snapshot.resources().vcpu()); object.setDouble("memory", snapshot.resources().memoryGb()); object.setDouble("disk", snapshot.resources().diskGb()); object.setString("architecture", snapshot.resources().architecture().name()); + object.setString("version", snapshot.getVersion().toFullString()); + object.setDouble("gpuMemoryGb", snapshot.resources().gpuResources().memoryGb()); + object.setLong("gpuCount", snapshot.resources().gpuResources().count()); }); return slime; } diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json index cf7738efe7f..328329e2b60 100644 --- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json +++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/controller/responses/metering.json @@ -6,7 +6,10 @@ "cpu": 12.0, "memory": 48.0, "disk": 1200.0, - "architecture": "arm64" + "architecture": "arm64", + "version": "0.0.0", + "gpuMemoryGb": 0.0, + "gpuCount": 0 }, { "applicationId": "tenant.app.instance", @@ -15,6 +18,9 @@ "cpu": 24.0, "memory": 96.0, "disk": 2400.0, - "architecture": "x86_64" + "architecture": "x86_64", + "version": "0.0.0", + "gpuMemoryGb": 0.0, + "gpuCount": 0 } ] diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/NodeSpec.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/NodeSpec.java index e54b91d9c67..d217d038e42 100644 --- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/NodeSpec.java +++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/NodeSpec.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.node.admin.configserver.noderepository; import com.fasterxml.jackson.databind.JsonNode; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; @@ -30,6 +31,7 @@ public class NodeSpec { private final String id; private final NodeState state; private final NodeType type; + private final CloudAccount cloudAccount; private final String flavor; private final Optional<DockerImage> wantedDockerImage; @@ -82,6 +84,7 @@ public class NodeSpec { Optional<DockerImage> currentDockerImage, NodeState state, NodeType type, + CloudAccount cloudAccount, String flavor, Optional<Version> wantedVespaVersion, Optional<Version> currentVespaVersion, @@ -125,6 +128,7 @@ public class NodeSpec { this.currentDockerImage = Objects.requireNonNull(currentDockerImage); this.state = Objects.requireNonNull(state); this.type = Objects.requireNonNull(type); + this.cloudAccount = Objects.requireNonNull(cloudAccount); this.flavor = Objects.requireNonNull(flavor); this.modelName = Objects.requireNonNull(modelName); this.wantedVespaVersion = Objects.requireNonNull(wantedVespaVersion); @@ -171,6 +175,10 @@ public class NodeSpec { return type; } + public CloudAccount cloudAccount() { + return cloudAccount; + } + public String flavor() { return flavor; } @@ -318,6 +326,7 @@ public class NodeSpec { Objects.equals(currentDockerImage, that.currentDockerImage) && Objects.equals(state, that.state) && Objects.equals(type, that.type) && + Objects.equals(cloudAccount, that.cloudAccount) && Objects.equals(flavor, that.flavor) && Objects.equals(modelName, that.modelName) && Objects.equals(wantedVespaVersion, that.wantedVespaVersion) && @@ -356,6 +365,7 @@ public class NodeSpec { currentDockerImage, state, type, + cloudAccount, flavor, modelName, wantedVespaVersion, @@ -394,6 +404,7 @@ public class NodeSpec { + " currentDockerImage=" + currentDockerImage + " state=" + state + " type=" + type + + " cloudAccount=" + cloudAccount + " flavor=" + flavor + " modelName=" + modelName + " wantedVespaVersion=" + wantedVespaVersion @@ -429,6 +440,7 @@ public class NodeSpec { private String id; private NodeState state; private NodeType type; + private CloudAccount cloudAccount = CloudAccount.empty; private String flavor; private Optional<DockerImage> wantedDockerImage = Optional.empty(); private Optional<DockerImage> currentDockerImage = Optional.empty(); @@ -526,6 +538,11 @@ public class NodeSpec { return this; } + public Builder cloudAccount(CloudAccount cloudAccount) { + this.cloudAccount = cloudAccount; + return this; + } + public Builder flavor(String flavor) { this.flavor = flavor; return this; @@ -720,6 +737,10 @@ public class NodeSpec { return type; } + public CloudAccount cloudAccount() { + return cloudAccount; + } + public String flavor() { return flavor; } @@ -801,7 +822,7 @@ public class NodeSpec { } public NodeSpec build() { - return new NodeSpec(hostname, id, wantedDockerImage, currentDockerImage, state, type, flavor, + return new NodeSpec(hostname, id, wantedDockerImage, currentDockerImage, state, type, cloudAccount, flavor, wantedVespaVersion, currentVespaVersion, wantedOsVersion, currentOsVersion, orchestratorStatus, owner, membership, wantedRestartGeneration, currentRestartGeneration, diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepository.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepository.java index 3a7e12f5661..b26b9d2d0e4 100644 --- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepository.java +++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepository.java @@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.node.admin.configserver.noderepository; import com.fasterxml.jackson.databind.JsonNode; import com.yahoo.component.Version; import com.yahoo.config.provision.ApplicationId; +import com.yahoo.config.provision.CloudAccount; import com.yahoo.config.provision.DockerImage; import com.yahoo.config.provision.HostName; import com.yahoo.config.provision.NodeResources; @@ -202,6 +203,7 @@ public class RealNodeRepository implements NodeRepository { Optional.ofNullable(node.currentDockerImage).map(DockerImage::fromString), nodeState, nodeType, + Optional.ofNullable(node.cloudAccount).map(CloudAccount::from).orElse(CloudAccount.empty), node.flavor, Optional.ofNullable(node.wantedVespaVersion).map(Version::fromString), Optional.ofNullable(node.vespaVersion).map(Version::fromString), diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/NodeRepositoryNode.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/NodeRepositoryNode.java index eb7ceab6021..8078b3acf6f 100644 --- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/NodeRepositoryNode.java +++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/NodeRepositoryNode.java @@ -27,6 +27,8 @@ public class NodeRepositoryNode { public Set<String> additionalIpAddresses; @JsonProperty("id") public String id; + @JsonProperty("cloudAccount") + public String cloudAccount; @JsonProperty("flavor") public String flavor; @JsonProperty("resources") diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepositoryTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepositoryTest.java index 00a805790f1..12816e1b8a3 100644 --- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepositoryTest.java +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/RealNodeRepositoryTest.java @@ -68,7 +68,7 @@ public class RealNodeRepositoryTest { for (int i = 0; i < 3; i++) { try { int port = findRandomOpenPort(); - container = JDisc.fromServicesXml(ContainerConfig.servicesXmlV2(port, SystemName.main, CloudAccount.empty), Networking.enable); + container = JDisc.fromServicesXml(ContainerConfig.servicesXmlV2(port, SystemName.main, CloudAccount.from("123456789012")), Networking.enable); ConfigServerApi configServerApi = ConfigServerApiImpl.createForTesting( List.of(URI.create("http://127.0.0.1:" + port))); waitForJdiscContainerToServe(configServerApi); @@ -124,6 +124,7 @@ public class RealNodeRepositoryTest { Optional<NodeSpec> node = nodeRepositoryApi.getOptionalNode(hostname); assertTrue(node.isPresent()); assertEquals(hostname, node.get().hostname()); + assertEquals(CloudAccount.from("123456789012"), node.get().cloudAccount()); } @Test diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index 526e6ed5a4e..1eef438a64e 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -38,6 +38,7 @@ import java.util.List; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.stream.Stream; /** * Implementation of the host provisioner API for hosted Vespa, using the node repository to allocate nodes. @@ -85,11 +86,7 @@ public class NodeRepositoryProvisioner implements Provisioner { ProvisionLogger logger) { log.log(Level.FINE, "Received deploy prepare request for " + requested + " for application " + application + ", cluster " + cluster); - - if (cluster.group().isPresent()) throw new IllegalArgumentException("Node requests cannot specify a group"); - - nodeResourceLimits.ensureWithinAdvertisedLimits("Min", requested.minResources().nodeResources(), application, cluster); - nodeResourceLimits.ensureWithinAdvertisedLimits("Max", requested.maxResources().nodeResources(), application, cluster); + validate(application, cluster, requested); int groups; NodeResources resources; @@ -116,6 +113,16 @@ public class NodeRepositoryProvisioner implements Provisioner { requireCompatibleResources(resources, cluster)); } + private void validate(ApplicationId application, ClusterSpec cluster, Capacity requested) { + if (cluster.group().isPresent()) throw new IllegalArgumentException("Node requests cannot specify a group"); + + nodeResourceLimits.ensureWithinAdvertisedLimits("Min", requested.minResources().nodeResources(), application, cluster); + nodeResourceLimits.ensureWithinAdvertisedLimits("Max", requested.maxResources().nodeResources(), application, cluster); + + if ( ! requested.minResources().nodeResources().gpuResources().equals(requested.maxResources().nodeResources().gpuResources())) + throw new IllegalArgumentException(requested + " is invalid: Gpu capacity cannot have ranges"); + } + private NodeResources getNodeResources(ClusterSpec cluster, NodeResources nodeResources, ApplicationId applicationId) { return nodeResources.isUnspecified() ? capacityPolicies.defaultNodeResources(cluster, applicationId) diff --git a/parent/pom.xml b/parent/pom.xml index 48e28895891..fe99e72c03e 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -77,7 +77,6 @@ <configuration> <release>17</release> <showWarnings>true</showWarnings> - <optimize>true</optimize> <showDeprecation>false</showDeprecation> <compilerArgs> <arg>-Xlint:all</arg> diff --git a/searchlib/src/tests/docstore/logdatastore/logdatastore_test.cpp b/searchlib/src/tests/docstore/logdatastore/logdatastore_test.cpp index 580fd199806..687f3624b44 100644 --- a/searchlib/src/tests/docstore/logdatastore/logdatastore_test.cpp +++ b/searchlib/src/tests/docstore/logdatastore/logdatastore_test.cpp @@ -1010,6 +1010,14 @@ TEST_F("require that lid space can be increased after being compacted and then s TEST_DO(f.assertContent({1,2}, 3)); } +TEST_F("require that there is control of static memory usage", Fixture) +{ + vespalib::MemoryUsage usage = f.store.getMemoryUsage(); + EXPECT_EQUAL(624u, sizeof(LogDataStore)); + EXPECT_EQUAL(74116u, usage.allocatedBytes()); + EXPECT_EQUAL(392u, usage.usedBytes()); +} + TEST_F("require that lid space can be shrunk only after read guards are deleted", Fixture) { f.write(1).write(2); diff --git a/searchlib/src/vespa/searchlib/attribute/enumstore.h b/searchlib/src/vespa/searchlib/attribute/enumstore.h index 59524f3788a..266437fafa1 100644 --- a/searchlib/src/vespa/searchlib/attribute/enumstore.h +++ b/searchlib/src/vespa/searchlib/attribute/enumstore.h @@ -16,7 +16,6 @@ #include <vespa/vespalib/datastore/unique_store.h> #include <vespa/vespalib/datastore/unique_store_string_allocator.h> #include <vespa/vespalib/util/buffer.h> -#include <vespa/vespalib/util/array.h> #include <vespa/vespalib/stllike/allocator.h> #include <vespa/vespalib/util/stringfmt.h> #include <cmath> diff --git a/searchlib/src/vespa/searchlib/docstore/chunk.cpp b/searchlib/src/vespa/searchlib/docstore/chunk.cpp index e83b190a7c0..a8982c28805 100644 --- a/searchlib/src/vespa/searchlib/docstore/chunk.cpp +++ b/searchlib/src/vespa/searchlib/docstore/chunk.cpp @@ -15,7 +15,7 @@ Chunk::append(uint32_t lid, const void * buffer, size_t len) std::lock_guard guard(_lock); os << lid << static_cast<uint32_t>(len); os.write(buffer, len); - _lids.push_back(Entry(lid, len, oldSz)); + _lids.emplace_back(lid, len, oldSz); return LidMeta(lid, len); } @@ -91,7 +91,7 @@ Chunk::Chunk(uint32_t id, const void * buffer, size_t len, bool skipcrc) : ssize_t oldRp(os.rp()); os >> lid >> sz; os.adjustReadPos(sz); - _lids.push_back(Entry(lid, sz, oldRp)); + _lids.emplace_back(lid, sz, oldRp); } os >> _lastSerial; } @@ -143,8 +143,8 @@ Chunk::getUniqueLids() const } LidList unique; unique.reserve(last.size()); - for (auto it(last.begin()), mt(last.end()); it != mt; it++) { - unique.push_back(it->second); + for (const auto & entry : last) { + unique.emplace_back(entry.second); } return unique; } diff --git a/searchlib/src/vespa/searchlib/docstore/chunk.h b/searchlib/src/vespa/searchlib/docstore/chunk.h index 93fc98311cd..e274572c96b 100644 --- a/searchlib/src/vespa/searchlib/docstore/chunk.h +++ b/searchlib/src/vespa/searchlib/docstore/chunk.h @@ -21,17 +21,12 @@ class ChunkFormat; class ChunkMeta { public: - ChunkMeta() : - _offset(0), - _lastSerial(0), - _size(0), - _numEntries(0) - { } - ChunkMeta(uint64_t offset, uint32_t size, uint64_t lastSerial, uint32_t numEntries) : - _offset(offset), - _lastSerial(lastSerial), - _size(size), - _numEntries(numEntries) + ChunkMeta() noexcept : ChunkMeta(0, 0, 0, 0) { } + ChunkMeta(uint64_t offset, uint32_t size, uint64_t lastSerial, uint32_t numEntries) noexcept + : _offset(offset), + _lastSerial(lastSerial), + _size(size), + _numEntries(numEntries) { } uint32_t getNumEntries() const { return _numEntries; } uint32_t getSize() const { return _size; } @@ -49,8 +44,8 @@ private: class LidMeta { public: - LidMeta() noexcept : _lid(0), _size(0) { } - LidMeta(uint32_t lid, uint32_t sz) : _lid(lid), _size(sz) { } + LidMeta() noexcept : LidMeta(0, 0) { } + LidMeta(uint32_t lid, uint32_t sz) noexcept : _lid(lid), _size(sz) { } uint32_t getLid() const { return _lid; } uint32_t size() const { return _size; } vespalib::nbostream & deserialize(vespalib::nbostream & is); @@ -66,15 +61,15 @@ public: using CompressionConfig = vespalib::compression::CompressionConfig; class Config { public: - Config(size_t maxBytes) : _maxBytes(maxBytes) { } + Config(size_t maxBytes) noexcept : _maxBytes(maxBytes) { } size_t getMaxBytes() const { return _maxBytes; } private: size_t _maxBytes; }; class Entry { public: - Entry() : _lid(0), _sz(0), _offset(0) { } - Entry(uint32_t lid, uint32_t sz, uint32_t offset) : _lid(lid), _sz(sz), _offset(offset) { } + Entry() noexcept : Entry(0, 0, 0 ) { } + Entry(uint32_t lid, uint32_t sz, uint32_t offset) noexcept : _lid(lid), _sz(sz), _offset(offset) { } uint32_t getLid() const { return _lid; } uint32_t size() const { return _sz + 2*4; } uint32_t netSize() const { return _sz; } @@ -101,7 +96,6 @@ public: void pack(uint64_t lastSerial, vespalib::DataBuffer & buffer, CompressionConfig compression); uint64_t getLastSerial() const { return _lastSerial; } uint32_t getId() const { return _id; } - bool validSerial() const { return getLastSerial() != static_cast<uint64_t>(-1l); } vespalib::ConstBufferRef getLid(uint32_t lid) const; const vespalib::nbostream & getData() const; bool hasRoom(size_t len) const; diff --git a/searchlib/src/vespa/searchlib/docstore/filechunk.cpp b/searchlib/src/vespa/searchlib/docstore/filechunk.cpp index a280ae08b46..d7922fcca2a 100644 --- a/searchlib/src/vespa/searchlib/docstore/filechunk.cpp +++ b/searchlib/src/vespa/searchlib/docstore/filechunk.cpp @@ -14,7 +14,6 @@ #include <vespa/vespalib/util/executor.h> #include <vespa/vespalib/util/arrayqueue.hpp> #include <vespa/vespalib/util/array.hpp> -#include <vespa/vespalib/stllike/hash_map.hpp> #include <vespa/fastos/file.h> #include <future> @@ -37,7 +36,7 @@ const vespalib::string DOC_ID_LIMIT_KEY("docIdLimit"); using vespalib::make_string; -FileChunk::ChunkInfo::ChunkInfo(uint64_t offset, uint32_t size, uint64_t lastSerial) +FileChunk::ChunkInfo::ChunkInfo(uint64_t offset, uint32_t size, uint64_t lastSerial) noexcept : _lastSerial(lastSerial), _offset(offset), _size(size) @@ -130,7 +129,7 @@ public: } }; -using TmpChunkMetaV = vespalib::Array<TmpChunkMeta>; +using TmpChunkMetaV = std::vector<TmpChunkMeta>; namespace { @@ -182,7 +181,7 @@ FileChunk::updateLidMap(const unique_lock &guard, ISetLid &ds, uint64_t serialNu tempVector.reserve(fileSize/(sizeof(ChunkMeta)+sizeof(LidMeta))); while ( ! is.empty() && is.good()) { const int64_t lastKnownGoodPos = _idxHeaderLen + is.rp(); - tempVector.push_back(TmpChunkMeta()); + tempVector.emplace_back(); TmpChunkMeta & chunkMeta(tempVector.back()); try { chunkMeta.deserialize(is); @@ -239,7 +238,7 @@ FileChunk::updateLidMap(const unique_lock &guard, ISetLid &ds, uint64_t serialNu } serialNum = chunkMeta.getLastSerial(); addNumBuckets(bucketMap.getNumBuckets()); - _chunkInfo.push_back(ChunkInfo(chunkMeta.getOffset(), chunkMeta.getSize(), chunkMeta.getLastSerial())); + _chunkInfo.emplace_back(chunkMeta.getOffset(), chunkMeta.getSize(), chunkMeta.getLastSerial()); assert(serialNum >= _lastPersistedSerialNum.load(std::memory_order_relaxed)); _lastPersistedSerialNum.store(serialNum, std::memory_order_relaxed); } @@ -531,7 +530,7 @@ FileChunk::getMemoryFootprint() const size_t FileChunk::getMemoryMetaFootprint() const { - return sizeof(*this) + _chunkInfo.byteCapacity(); + return sizeof(*this) + _chunkInfo.capacity()*sizeof(ChunkInfoVector::value_type); } vespalib::MemoryUsage @@ -540,8 +539,8 @@ FileChunk::getMemoryUsage() const vespalib::MemoryUsage result; result.incAllocatedBytes(sizeof(*this)); result.incUsedBytes(sizeof(*this)); - result.incAllocatedBytes(_chunkInfo.byteCapacity()); - result.incUsedBytes(_chunkInfo.byteSize()); + result.incAllocatedBytes(_chunkInfo.capacity()*sizeof(ChunkInfoVector::value_type)); + result.incUsedBytes(_chunkInfo.size()*sizeof(ChunkInfoVector::value_type)); return result; } diff --git a/searchlib/src/vespa/searchlib/docstore/filechunk.h b/searchlib/src/vespa/searchlib/docstore/filechunk.h index 8788430a5df..9e8623060fb 100644 --- a/searchlib/src/vespa/searchlib/docstore/filechunk.h +++ b/searchlib/src/vespa/searchlib/docstore/filechunk.h @@ -8,7 +8,6 @@ #include "randread.h" #include <vespa/searchlib/common/tunefileinfo.h> #include <vespa/vespalib/stllike/hash_map.h> -#include <vespa/vespalib/util/array.h> #include <vespa/vespalib/util/cpu_usage.h> #include <vespa/vespalib/util/generationhandler.h> #include <vespa/vespalib/util/memoryusage.h> @@ -163,7 +162,6 @@ public: virtual vespalib::system_time getModificationTime() const; virtual bool frozen() const { return true; } const vespalib::string & getName() const { return _name; } - void compact(const IGetLid & iGetLid); void appendTo(vespalib::Executor & executor, const IGetLid & db, IWriteData & dest, uint32_t numChunks, IFileChunkVisitorProgress *visitorProgress, vespalib::CpuUsage::Category cpu_category); @@ -202,7 +200,6 @@ public: static vespalib::string createDatFileName(const vespalib::string & name); private: using File = std::unique_ptr<FileRandRead>; - void loadChunkInfo(); const FileId _fileId; const NameId _nameId; const vespalib::string _name; @@ -221,8 +218,8 @@ protected: class ChunkInfo { public: - ChunkInfo() : _lastSerial(0), _offset(0), _size(0) { } - ChunkInfo(uint64_t offset, uint32_t size, uint64_t lastSerial); + ChunkInfo() noexcept : _lastSerial(0), _offset(0), _size(0) { } + ChunkInfo(uint64_t offset, uint32_t size, uint64_t lastSerial) noexcept; uint64_t getOffset() const { return _offset; } uint32_t getSize() const { return _size; } uint64_t getLastSerial() const { return _lastSerial; } @@ -240,7 +237,7 @@ protected: static uint32_t readDocIdLimit(vespalib::GenericHeader &header); static void writeDocIdLimit(vespalib::GenericHeader &header, uint32_t docIdLimit); - using ChunkInfoVector = vespalib::Array<ChunkInfo>; + using ChunkInfoVector = std::vector<ChunkInfo, vespalib::allocator_large<ChunkInfo>>; const IBucketizer * _bucketizer; size_t _addedBytes; TuneFileSummary _tune; diff --git a/searchlib/src/vespa/searchlib/docstore/lid_info.h b/searchlib/src/vespa/searchlib/docstore/lid_info.h index 24bc6a59664..72da441bbee 100644 --- a/searchlib/src/vespa/searchlib/docstore/lid_info.h +++ b/searchlib/src/vespa/searchlib/docstore/lid_info.h @@ -14,29 +14,29 @@ public: LidInfo() noexcept : _value() { } LidInfo(uint64_t rep) noexcept { _value.r = rep; } LidInfo(uint32_t fileId, uint32_t chunkId, uint32_t size); - uint32_t getFileId() const { return _value.v.fileId; } - uint32_t getChunkId() const { return _value.v.chunkId; } - uint32_t size() const { return _value.v.size << SIZE_SHIFT; } - operator uint64_t () const { return _value.r; } - bool empty() const { return size() == 0; } - bool valid() const { return _value.r != std::numeric_limits<uint64_t>::max(); } + uint32_t getFileId() const noexcept { return _value.v.fileId; } + uint32_t getChunkId() const noexcept { return _value.v.chunkId; } + uint32_t size() const noexcept { return _value.v.size << SIZE_SHIFT; } + operator uint64_t () const noexcept { return _value.r; } + bool empty() const noexcept { return size() == 0; } + bool valid() const noexcept { return _value.r != std::numeric_limits<uint64_t>::max(); } - bool operator==(const LidInfo &b) const { + bool operator==(const LidInfo &b) const noexcept { return (getFileId() == b.getFileId()) && (getChunkId() == b.getChunkId()); } - bool operator < (const LidInfo &b) const { + bool operator < (const LidInfo &b) const noexcept { return (getFileId() == b.getFileId()) ? (getChunkId() < b.getChunkId()) : (getFileId() < b.getFileId()); } - static uint32_t getFileIdLimit() { return 1 << NUM_FILE_BITS; } - static uint32_t getChunkIdLimit() { return 1 << NUM_CHUNK_BITS; } + static constexpr uint32_t getFileIdLimit() { return 1 << NUM_FILE_BITS; } + static constexpr uint32_t getChunkIdLimit() { return 1 << NUM_CHUNK_BITS; } private: - static uint32_t computeAlignedSize(uint32_t sz) { + static constexpr uint32_t computeAlignedSize(uint32_t sz) { return (sz+((1<<SIZE_SHIFT)-1)) >> SIZE_SHIFT; } - static uint32_t getSizeLimit() { + static constexpr uint32_t getSizeLimit() { return std::numeric_limits<uint32_t>::max() - ((2<<SIZE_SHIFT)-2); } static constexpr uint32_t NUM_FILE_BITS = 16; diff --git a/searchlib/src/vespa/searchlib/docstore/logdatastore.cpp b/searchlib/src/vespa/searchlib/docstore/logdatastore.cpp index e76caba55a1..f35f9fa4cec 100644 --- a/searchlib/src/vespa/searchlib/docstore/logdatastore.cpp +++ b/searchlib/src/vespa/searchlib/docstore/logdatastore.cpp @@ -82,8 +82,11 @@ LogDataStore::LogDataStore(vespalib::Executor &executor, const vespalib::string _compactLidSpaceGeneration() { // Reserve space for 1TB summary in order to avoid locking. - _fileChunks.reserve(LidInfo::getFileIdLimit()); - _holdFileChunks.resize(LidInfo::getFileIdLimit()); + // Even if we have reserved 16 bits for file id there is no chance that we will even get close to that. + // Size of files grows with disk size, so 8k files should be more than sufficient. + // File ids are reused so there should be no chance of running empty. + static_assert(LidInfo::getFileIdLimit() == 65536u); + _fileChunks.reserve(8_Ki); preload(); updateLidMap(getLastFileChunkDocIdLimit()); @@ -216,7 +219,7 @@ LogDataStore::requireSpace(MonitorGuard guard, WriteableFileChunk & active, CpuU FileId fileId = allocateFileId(guard); setNewFileChunk(guard, createWritableFile(fileId, active.getSerialNum())); setActive(guard, fileId); - std::unique_ptr<FileChunkHolder> activeHolder = holdFileChunk(active.getFileId()); + std::unique_ptr<FileChunkHolder> activeHolder = holdFileChunk(guard, active.getFileId()); guard.unlock(); // Write chunks to old .dat file // Note: Feed latency spike @@ -319,7 +322,7 @@ LogDataStore::flush(uint64_t syncToken) // but is a fundamental part of the WRITE pipeline of the data store. getActive(guard).flush(true, syncToken, CpuCategory::WRITE); active = &getActive(guard); - activeHolder = holdFileChunk(active->getFileId()); + activeHolder = holdFileChunk(guard, active->getFileId()); } active->flushPendingChunks(syncToken); activeHolder.reset(); @@ -488,7 +491,7 @@ void LogDataStore::compactFile(FileId fileId) MonitorGuard guard(_updateLock); _genHandler.update_oldest_used_generation(); if (currentGeneration < _genHandler.get_oldest_used_generation()) { - if (_holdFileChunks[fc->getFileId().getId()] == 0u) { + if (canFileChunkBeDropped(guard, fc->getFileId())) { toDie = std::move(fc); break; } @@ -536,13 +539,13 @@ LogDataStore::memoryMeta() const FileChunk::FileId LogDataStore::allocateFileId(const MonitorGuard & guard) { - (void) guard; + assert(guard.owns_lock()); for (size_t i(0); i < _fileChunks.size(); i++) { if ( ! _fileChunks[i] ) { return FileId(i); } } - // This assert is verify that we have not gotten ourselves into a mess + // This assert is to verify that we have not gotten ourselves into a mess // that would require the use of locks to prevent. Just assure that the // below resize is 'safe'. assert(_fileChunks.capacity() > _fileChunks.size()); @@ -1126,11 +1129,16 @@ public: }; std::unique_ptr<LogDataStore::FileChunkHolder> -LogDataStore::holdFileChunk(FileId fileId) +LogDataStore::holdFileChunk(const MonitorGuard & guard, FileId fileId) { - assert(fileId.getId() < _holdFileChunks.size()); - assert(_holdFileChunks[fileId.getId()] < 2000u); - ++_holdFileChunks[fileId.getId()]; + assert(guard.owns_lock()); + auto found = _holdFileChunks.find(fileId.getId()); + if (found == _holdFileChunks.end()) { + _holdFileChunks[fileId.getId()] = 1; + } else { + assert(found->second < 2000u); + found->second++; + } return std::make_unique<FileChunkHolder>(*this, fileId); } @@ -1138,12 +1146,20 @@ void LogDataStore::unholdFileChunk(FileId fileId) { MonitorGuard guard(_updateLock); - assert(fileId.getId() < _holdFileChunks.size()); - assert(_holdFileChunks[fileId.getId()] > 0u); - --_holdFileChunks[fileId.getId()]; + auto found = _holdFileChunks.find(fileId.getId()); + assert(found != _holdFileChunks.end()); + assert(found->second > 0u); + if (--found->second == 0u) { + _holdFileChunks.erase(found); + } // No signalling, compactWorst() sleeps and retries } +bool LogDataStore::canFileChunkBeDropped(const MonitorGuard & guard, FileId fileId) const { + assert(guard.owns_lock()); + return ! _holdFileChunks.contains(fileId.getId()); +} + DataStoreStorageStats LogDataStore::getStorageStats() const { @@ -1169,6 +1185,14 @@ LogDataStore::getMemoryUsage() const result.merge(fileChunk->getMemoryUsage()); } } + size_t extra_allocated = 0; + extra_allocated += _fileChunks.capacity() * sizeof(FileChunkVector::value_type); + extra_allocated += _holdFileChunks.capacity() * sizeof(uint32_t); + size_t extra_used = 0; + extra_used += _fileChunks.size() * sizeof(FileChunkVector::value_type); + extra_used += _holdFileChunks.size() * sizeof(uint32_t); + result.incAllocatedBytes(extra_allocated); + result.incUsedBytes(extra_used); return result; } diff --git a/searchlib/src/vespa/searchlib/docstore/logdatastore.h b/searchlib/src/vespa/searchlib/docstore/logdatastore.h index 3289ceb19ba..ef2cbf93215 100644 --- a/searchlib/src/vespa/searchlib/docstore/logdatastore.h +++ b/searchlib/src/vespa/searchlib/docstore/logdatastore.h @@ -227,16 +227,12 @@ private: size_t computeNumberOfSignificantBucketIdBits(const IBucketizer & bucketizer, FileId fileId) const; - /* - * Protect against compactWorst() dropping file chunk. Caller must hold - * _updateLock. - */ - std::unique_ptr<FileChunkHolder> holdFileChunk(FileId fileId); + /// Protect against compactWorst() dropping file chunk. Caller must hold _updateLock. + std::unique_ptr<FileChunkHolder> holdFileChunk(const MonitorGuard & guard, FileId fileId); - /* - * Drop protection against compactWorst() dropping file chunk. - */ + /// Drop protection against compactWorst() dropping file chunk. void unholdFileChunk(FileId fileId); + bool canFileChunkBeDropped(const MonitorGuard & guard, FileId fileId) const; SerialNum flushFile(MonitorGuard guard, WriteableFileChunk & file, SerialNum syncToken, vespalib::CpuUsage::Category cpu_category); @@ -258,7 +254,7 @@ private: mutable vespalib::GenerationHandler _genHandler; LidInfoVector _lidInfo; FileChunkVector _fileChunks; - std::vector<uint32_t> _holdFileChunks; + vespalib::hash_map<uint32_t, uint32_t> _holdFileChunks; FileId _active; FileId _prevActive; mutable std::mutex _updateLock; diff --git a/searchlib/src/vespa/searchlib/docstore/writeablefilechunk.cpp b/searchlib/src/vespa/searchlib/docstore/writeablefilechunk.cpp index 4248f42a5b4..c642d8b30f0 100644 --- a/searchlib/src/vespa/searchlib/docstore/writeablefilechunk.cpp +++ b/searchlib/src/vespa/searchlib/docstore/writeablefilechunk.cpp @@ -9,7 +9,6 @@ #include <vespa/vespalib/data/fileheader.h> #include <vespa/vespalib/objects/nbostream.h> #include <vespa/vespalib/stllike/hash_map.hpp> -#include <vespa/vespalib/util/array.hpp> #include <vespa/vespalib/util/cpu_usage.h> #include <vespa/vespalib/util/lambdatask.h> #include <vespa/vespalib/util/size_literals.h> @@ -78,7 +77,7 @@ WriteableFileChunk:: WriteableFileChunk(vespalib::Executor &executor, FileId fileId, NameId nameId, const vespalib::string &baseName, - SerialNum initialSerialNum, + uint64_t initialSerialNum, uint32_t docIdLimit, const Config &config, const TuneFileSummary &tune, @@ -101,7 +100,7 @@ WriteableFileChunk(vespalib::Executor &executor, _idxFileSize(0), _currentDiskFootprint(0), _nextChunkId(1), - _active(new Chunk(0, Chunk::Config(config.getMaxChunkBytes()))), + _active(std::make_unique<Chunk>(0, Chunk::Config(config.getMaxChunkBytes()))), _alignment(1), _granularity(1), _maxChunkSize(0x100000), @@ -185,7 +184,6 @@ WriteableFileChunk::updateLidMap(const unique_lock &guard, ISetLid &ds, uint64_t _serialNum = getLastPersistedSerialNum(); _firstChunkIdToBeWritten = _active->getId(); setDiskFootprint(0); - _chunkInfo.reserve(0x10000); return sz; } diff --git a/searchlib/src/vespa/searchlib/docstore/writeablefilechunk.h b/searchlib/src/vespa/searchlib/docstore/writeablefilechunk.h index 37bb925f11e..defa9a382c8 100644 --- a/searchlib/src/vespa/searchlib/docstore/writeablefilechunk.h +++ b/searchlib/src/vespa/searchlib/docstore/writeablefilechunk.h @@ -4,7 +4,6 @@ #include "filechunk.h" #include <vespa/vespalib/util/executor.h> -#include <vespa/searchlib/transactionlog/syncproxy.h> #include <vespa/fastos/file.h> #include <map> #include <deque> @@ -24,9 +23,9 @@ public: { public: using CompressionConfig = vespalib::compression::CompressionConfig; - Config() : Config({CompressionConfig::LZ4, 9, 60}, 0x10000) { } + Config() noexcept : Config({CompressionConfig::LZ4, 9, 60}, 0x10000) { } - Config(CompressionConfig compression, size_t maxChunkBytes) + Config(CompressionConfig compression, size_t maxChunkBytes) noexcept : _compression(compression), _maxChunkBytes(maxChunkBytes) { } @@ -107,7 +106,7 @@ private: const Chunk& get_chunk(uint32_t chunk) const; Config _config; - SerialNum _serialNum; + uint64_t _serialNum; std::atomic<bool> _frozen; // Lock order is _writeLock, _flushLock, _lock mutable std::mutex _lock; diff --git a/searchlib/src/vespa/searchlib/fef/rank_program.h b/searchlib/src/vespa/searchlib/fef/rank_program.h index e988aad665d..a67f0495b8c 100644 --- a/searchlib/src/vespa/searchlib/fef/rank_program.h +++ b/searchlib/src/vespa/searchlib/fef/rank_program.h @@ -8,7 +8,6 @@ #include "matchdata.h" #include "feature_resolver.h" #include <vespa/vespalib/stllike/string.h> -#include <vespa/vespalib/util/array.h> #include <vespa/vespalib/util/stash.h> #include <vespa/vespalib/stllike/hash_set.h> diff --git a/searchlib/src/vespa/searchlib/queryeval/wand/wand_parts.h b/searchlib/src/vespa/searchlib/queryeval/wand/wand_parts.h index e2f0a78fb52..b0be4e9db5e 100644 --- a/searchlib/src/vespa/searchlib/queryeval/wand/wand_parts.h +++ b/searchlib/src/vespa/searchlib/queryeval/wand/wand_parts.h @@ -10,7 +10,6 @@ #include <vespa/searchlib/queryeval/iterator_pack.h> #include <vespa/searchlib/attribute/iterator_pack.h> #include <vespa/vespalib/objects/objectvisitor.h> -#include <vespa/vespalib/util/array.h> #include <vespa/vespalib/util/priority_queue.h> #include <vespa/searchlib/attribute/i_document_weight_attribute.h> #include <vespa/vespalib/util/stringfmt.h> diff --git a/searchlib/src/vespa/searchlib/util/fileutil.h b/searchlib/src/vespa/searchlib/util/fileutil.h index e2f7e1a25c0..97bec4e1bba 100644 --- a/searchlib/src/vespa/searchlib/util/fileutil.h +++ b/searchlib/src/vespa/searchlib/util/fileutil.h @@ -22,10 +22,10 @@ public: LoadedBuffer & operator =(const LoadedBuffer & rhs) = delete; using UP = std::unique_ptr<LoadedBuffer>; - LoadedBuffer(void * buf, size_t sz) - : _buffer(buf), - _size(sz), - _header(nullptr) + LoadedBuffer(void * buf, size_t sz) noexcept + : _buffer(buf), + _size(sz), + _header(nullptr) { } virtual ~LoadedBuffer() = default; diff --git a/vespalib/src/vespa/vespalib/datastore/bufferstate.h b/vespalib/src/vespa/vespalib/datastore/bufferstate.h index c3e6110cc52..5b98099ed69 100644 --- a/vespalib/src/vespa/vespalib/datastore/bufferstate.h +++ b/vespalib/src/vespa/vespalib/datastore/bufferstate.h @@ -8,7 +8,6 @@ #include "entryref.h" #include <vespa/vespalib/util/generationhandler.h> #include <vespa/vespalib/util/alloc.h> -#include <vespa/vespalib/util/array.h> namespace vespalib::datastore { diff --git a/vespalib/src/vespa/vespalib/util/array.h b/vespalib/src/vespa/vespalib/util/array.h index 30fa4f3eb09..e9d8c9ccfdb 100644 --- a/vespalib/src/vespa/vespalib/util/array.h +++ b/vespalib/src/vespa/vespalib/util/array.h @@ -128,8 +128,6 @@ public: reverse_iterator rbegin() { return empty() ? array(0) : array(_sz) - 1; } reverse_iterator rend() { return empty() ? array(0) : array(0) - 1; } size_t size() const { return _sz; } - size_t byteSize() const { return _sz * sizeof(T); } - size_t byteCapacity() const { return _array.size(); } size_t capacity() const { return _array.size()/sizeof(T); } void clear() { std::destroy(array(0), array(_sz)); diff --git a/vespalib/src/vespa/vespalib/util/compressionconfig.h b/vespalib/src/vespa/vespalib/util/compressionconfig.h index 2a09fa7e086..726264f9fd7 100644 --- a/vespalib/src/vespa/vespalib/util/compressionconfig.h +++ b/vespalib/src/vespa/vespalib/util/compressionconfig.h @@ -31,16 +31,16 @@ struct CompressionConfig { CompressionConfig(Type t, uint8_t lvl, uint8_t minRes, size_t minSz) noexcept : minSize(minSz), type(t), compressionLevel(lvl), threshold(minRes) {} - bool operator==(const CompressionConfig& o) const { + bool operator==(const CompressionConfig& o) const noexcept { return (type == o.type && compressionLevel == o.compressionLevel && threshold == o.threshold); } - bool operator!=(const CompressionConfig& o) const { + bool operator!=(const CompressionConfig& o) const noexcept { return !operator==(o); } - static Type toType(uint32_t val) { + static Type toType(uint32_t val) noexcept { switch (val) { case 1: return NONE_MULTI; case 2: return HISTORIC_2; @@ -52,7 +52,7 @@ struct CompressionConfig { default: return NONE; } } - static Type toType(const char * val) { + static Type toType(const char * val) noexcept { if (strncasecmp(val, "lz4", 3) == 0) { return LZ4; } if (strncasecmp(val, "zstd", 4) == 0) { @@ -60,11 +60,11 @@ struct CompressionConfig { } return NONE; } - static bool isCompressed(Type type) { + static bool isCompressed(Type type) noexcept { return (type != CompressionConfig::NONE && type != CompressionConfig::UNCOMPRESSABLE); } - bool useCompression() const { return isCompressed(type); } + bool useCompression() const noexcept { return isCompressed(type); } uint32_t minSize; Type type; |