diff options
124 files changed, 1280 insertions, 1034 deletions
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/component/SignificanceModelRegistry.java b/config-model/src/main/java/com/yahoo/vespa/model/container/component/SignificanceModelRegistry.java index eb3f63cdf10..c210c2621a6 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/component/SignificanceModelRegistry.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/component/SignificanceModelRegistry.java @@ -23,19 +23,20 @@ import static com.yahoo.vespa.model.container.xml.ModelIdResolver.SIGNIFICANCE_M */ public class SignificanceModelRegistry extends SimpleComponent implements SignificanceConfig.Producer { - private static final String CLASS = "com.yahoo.search.significance.impl.DefaultSignificanceModelRegistry"; - private static final String BUNDLE = "linguistics"; + private static final String CLASS = "com.yahoo.language.significance.impl.DefaultSignificanceModelRegistry"; + private static final String BUNDLE = null; - private final List<SignificanceModelConfig> configList; + private final List<SignificanceModelConfig> configList = new ArrayList<>(); public SignificanceModelRegistry(DeployState deployState, Element spec) { super(new ComponentModel(BundleInstantiationSpecification.fromStrings(CLASS, CLASS, BUNDLE))); - configList = new ArrayList<>(); + if (spec != null) { - for (Element modelElement : XML.getChildren(spec, "model")) { - addConfig( - modelElement.getAttribute("language"), - Model.fromXml(deployState, modelElement, Set.of(SIGNIFICANCE_MODEL)).modelReference()); + for (Element modelElement : XML.getChildren(spec, "model")) { + addConfig( + modelElement.getAttribute("language"), + Model.fromXml(deployState, modelElement, Set.of(SIGNIFICANCE_MODEL)).modelReference()); + } } } diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java index c6fca8d32c6..56e2a21e38b 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java @@ -778,7 +778,6 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> { private void addSignificance(DeployState deployState, Element spec, ApplicationContainerCluster cluster) { Element significanceElement = XML.getChild(spec, "significance"); - if (significanceElement == null) return; SignificanceModelRegistry significanceModelRegistry = new SignificanceModelRegistry(deployState, significanceElement); cluster.addComponent(significanceModelRegistry); diff --git a/config-model/src/main/java/com/yahoo/vespa/model/content/ContentNode.java b/config-model/src/main/java/com/yahoo/vespa/model/content/ContentNode.java index 5ec23b53109..ba52664a660 100644 --- a/config-model/src/main/java/com/yahoo/vespa/model/content/ContentNode.java +++ b/config-model/src/main/java/com/yahoo/vespa/model/content/ContentNode.java @@ -37,6 +37,14 @@ public abstract class ContentNode extends AbstractService rpc_num_targets = featureFlags.rpcNumTargets(); rpc_events_before_wakeup = featureFlags.rpcEventsBeforeWakeup(); + // <node>-level distribution key range validation is initially done through the XML schema, + // but we also check it here in the case of programmatic content node instantiations. + // Only [0, UINT16_MAX - 1] is a valid range. UINT16_MAX is a special content layer-internal + // sentinel value that must never be used by actual nodes. + if (distributionKey < 0 || distributionKey >= 65535) { + throw new IllegalArgumentException("Distribution key %d is outside valid range [0, 65534]".formatted(distributionKey)); + } + initialize(); setProp("clustertype", "content"); setProp("clustername", clusterName); diff --git a/config-model/src/main/resources/schema/content.rnc b/config-model/src/main/resources/schema/content.rnc index 520f41609b2..0601741bb16 100644 --- a/config-model/src/main/resources/schema/content.rnc +++ b/config-model/src/main/resources/schema/content.rnc @@ -207,7 +207,7 @@ Documents = element documents { ContentNode = element node { GenericConfig* & service.attlist & - attribute distribution-key { xsd:nonNegativeInteger } & + attribute distribution-key { xsd:nonNegativeInteger { maxInclusive = "65534" } } & attribute capacity { xsd:double { minExclusive = "0.0" } }? & attribute mmap-core-limit { xsd:nonNegativeInteger }? & attribute core-on-oom { xsd:boolean }? & diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java index 5a316f69a9f..ea43f5c8124 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/container/search/searchchain/SchemaChainsTest.java @@ -159,7 +159,7 @@ public class SchemaChainsTest extends SchemaChainsTestBase { @Test public void require_all_default_chains_are_correct() { - assertEquals(61, chainsConfig.components().size()); + assertEquals(63, chainsConfig.components().size()); assertEquals(10, chainsConfig.chains().size()); validateVespaPhasesChain(findChain("vespaPhases")); validateNativeChain(findChain("native")); diff --git a/config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java index 96e1f2edf76..786caa4b317 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/content/ContentClusterTest.java @@ -54,6 +54,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -1260,7 +1261,7 @@ public class ContentClusterTest extends ContentBaseTest { } @Test - void verifyt_max_tls_size() throws Exception { + void verify_max_tls_size() throws Exception { var flavor = new Flavor(new FlavorsConfig.Flavor(new FlavorsConfig.Flavor.Builder().name("test").minDiskAvailableGb(100))); assertEquals(21474836480L, resolveMaxTLSSize(Optional.empty())); assertEquals(2147483648L, resolveMaxTLSSize(Optional.of(flavor))); @@ -1487,6 +1488,24 @@ public class ContentClusterTest extends ContentBaseTest { assertTrue(resolveDistributorOperationCancellationConfig(2)); } + @Test + void node_distribution_key_outside_legal_range_is_disallowed() { + // Only [0, UINT16_MAX - 1] is a valid range. UINT16_MAX is a special content layer-internal + // sentinel value that must never be used by actual nodes. + for (int distKey : List.of(-1, 65535, 65536, 100000)) { + assertThrows(IllegalArgumentException.class, () -> + parse(""" + <content version="1.0" id="storage"> + <documents/> + <redundancy>1</redundancy> + <group> + <node hostalias='mockhost' distribution-key='%d' /> + </group> + </content>""".formatted(distKey) + )); + } + } + private String servicesWithGroups(int groupCount, double minGroupUpRatio) { String services = String.format("<?xml version='1.0' encoding='UTF-8' ?>" + "<services version='1.0'>" + diff --git a/config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java b/config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java index acb9426b812..00e95a34287 100644 --- a/config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java +++ b/config-model/src/test/java/com/yahoo/vespa/model/significance/test/SignificanceModelTestCase.java @@ -49,9 +49,9 @@ public class SignificanceModelTestCase { private SignificanceConfig assertSignificancePresent(ApplicationContainerCluster cluster) { - var id = new ComponentId("com.yahoo.search.significance.impl.DefaultSignificanceModelRegistry"); + var id = new ComponentId("com.yahoo.language.significance.impl.DefaultSignificanceModelRegistry"); var significance = (SignificanceModelRegistry) cluster.getComponentsMap().get(id); - assertEquals("com.yahoo.search.significance.impl.DefaultSignificanceModelRegistry", significance.getClassId().getName()); + assertEquals("com.yahoo.language.significance.impl.DefaultSignificanceModelRegistry", significance.getClassId().getName()); var cfgBuilder = new SignificanceConfig.Builder(); significance.getConfig(cfgBuilder); return cfgBuilder.build(); diff --git a/configserver/src/main/resources/configserver-app/services.xml b/configserver/src/main/resources/configserver-app/services.xml index 069b7ffc496..fb6516ce6cf 100644 --- a/configserver/src/main/resources/configserver-app/services.xml +++ b/configserver/src/main/resources/configserver-app/services.xml @@ -147,7 +147,7 @@ <config name="jdisc.http.connector"> <!-- Limit max request content size accepted --> <maxContentSize>0</maxContentSize> <!-- 0 => scale based on max heap size --> - <maxContentSizeErrorMessageTemplate>Application package is too large (%1$d > %2$d bytes). Try increasing config server heap size by setting VESPA_CONFIGSERVER_JVMARGS. See https://docs.vespa.ai/en/performance/container-tuning.html#config-server-and-config-proxy.</maxContentSizeErrorMessageTemplate> + <maxContentSizeErrorMessageTemplate>Application package is too large (%1$d > %2$d bytes). Try increasing config server heap size by setting VESPA_CONFIGSERVER_JVMARGS. See https://docs.vespa.ai/en/performance/container-tuning.html#config-server-and-config-proxy</maxContentSizeErrorMessageTemplate> </config> </server> <preprocess:include file='http-server.xml' required='false' /> diff --git a/container-core/src/main/java/com/yahoo/container/handler/AccessLogRequestHandler.java b/container-core/src/main/java/com/yahoo/container/handler/AccessLogRequestHandler.java index 872ad82f746..a493905e6d0 100644 --- a/container-core/src/main/java/com/yahoo/container/handler/AccessLogRequestHandler.java +++ b/container-core/src/main/java/com/yahoo/container/handler/AccessLogRequestHandler.java @@ -19,7 +19,7 @@ import java.util.concurrent.Executor; /** * Exposes access log through http. * - * @author dybis + * @author Haakon Dybdahl */ public class AccessLogRequestHandler extends ThreadedHttpRequestHandler { diff --git a/container-core/src/main/java/com/yahoo/container/logging/CircularArrayAccessLogKeeper.java b/container-core/src/main/java/com/yahoo/container/logging/CircularArrayAccessLogKeeper.java index ba143794728..5d96f4d68c1 100644 --- a/container-core/src/main/java/com/yahoo/container/logging/CircularArrayAccessLogKeeper.java +++ b/container-core/src/main/java/com/yahoo/container/logging/CircularArrayAccessLogKeeper.java @@ -9,7 +9,7 @@ import java.util.List; /** * This class keeps some information from the access log from the requests in memory. It is thread-safe. * - * @author dybis + * @author Haakon Dybdahl */ public class CircularArrayAccessLogKeeper { public static final int SIZE = 1000; diff --git a/container-search/src/main/java/com/yahoo/search/searchchain/model/federation/LocalProviderSpec.java b/container-search/src/main/java/com/yahoo/search/searchchain/model/federation/LocalProviderSpec.java index 9ea35339f8d..97220725fec 100644 --- a/container-search/src/main/java/com/yahoo/search/searchchain/model/federation/LocalProviderSpec.java +++ b/container-search/src/main/java/com/yahoo/search/searchchain/model/federation/LocalProviderSpec.java @@ -43,7 +43,8 @@ public class LocalProviderSpec { com.yahoo.search.searchers.ValidateFuzzySearcher.class, com.yahoo.search.yql.FieldFiller.class, com.yahoo.search.searchers.InputCheckingSearcher.class, - com.yahoo.search.searchers.ContainerLatencySearcher.class); + com.yahoo.search.searchers.ContainerLatencySearcher.class, + com.yahoo.search.significance.SignificanceSearcher.class); public final String clusterName; diff --git a/container-search/src/main/java/com/yahoo/search/significance/SignificanceSearcher.java b/container-search/src/main/java/com/yahoo/search/significance/SignificanceSearcher.java new file mode 100644 index 00000000000..0a42bf8a259 --- /dev/null +++ b/container-search/src/main/java/com/yahoo/search/significance/SignificanceSearcher.java @@ -0,0 +1,77 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.search.significance; + +import com.yahoo.component.annotation.Inject; +import com.yahoo.component.chain.dependencies.Before; +import com.yahoo.component.chain.dependencies.Provides; +import com.yahoo.language.Language; +import com.yahoo.language.significance.SignificanceModel; +import com.yahoo.language.significance.SignificanceModelRegistry; +import com.yahoo.prelude.query.CompositeItem; +import com.yahoo.prelude.query.Item; +import com.yahoo.prelude.query.NullItem; +import com.yahoo.prelude.query.WordItem; +import com.yahoo.search.Query; +import com.yahoo.search.Result; +import com.yahoo.search.Searcher; +import com.yahoo.search.searchchain.Execution; + +import java.util.Optional; + +import static com.yahoo.prelude.querytransform.StemmingSearcher.STEMMING; + +/** + * Sets significance values on word items in the query tree. + * + * @author MariusArhaug + */ + +@Provides(SignificanceSearcher.SIGNIFICANCE) +@Before(STEMMING) +public class SignificanceSearcher extends Searcher { + + public final static String SIGNIFICANCE = "Significance"; + private final SignificanceModelRegistry significanceModelRegistry; + + + @Inject + public SignificanceSearcher(SignificanceModelRegistry significanceModelRegistry) { + this.significanceModelRegistry = significanceModelRegistry; + } + + @Override + public Result search(Query query, Execution execution) { + Language language = query.getModel().getParsingLanguage(); + Optional<SignificanceModel> model = significanceModelRegistry.getModel(language); + + if (model.isEmpty()) return execution.search(query); + + setIDF(query.getModel().getQueryTree().getRoot(), model.get()); + + return execution.search(query); + } + + private void setIDF(Item root, SignificanceModel significanceModel) { + if (root == null || root instanceof NullItem) return; + + if (root instanceof WordItem) { + + var documentFrequency = significanceModel.documentFrequency(((WordItem) root).getWord()); + long N = documentFrequency.corpusSize(); + long nq_i = documentFrequency.frequency(); + double idf = calculateIDF(N, nq_i); + + ((WordItem) root).setSignificance(idf); + } else if (root instanceof CompositeItem) { + for (int i = 0; i < ((CompositeItem) root).getItemCount(); i++) { + setIDF(((CompositeItem) root).getItem(i), significanceModel); + } + } + } + + public static double calculateIDF(long N, long nq_i) { + return Math.log(1 + (N - nq_i + 0.5) / (nq_i + 0.5)); + } +} + + diff --git a/container-search/src/test/java/com/yahoo/search/significance/model/en.json b/container-search/src/test/java/com/yahoo/search/significance/model/en.json new file mode 100644 index 00000000000..50bae5e3451 --- /dev/null +++ b/container-search/src/test/java/com/yahoo/search/significance/model/en.json @@ -0,0 +1,14 @@ +{ + "version" : "1.0", + "id" : "test::1", + "description" : "desc", + "corpus-size" : 10, + "language" : "en", + "word-count" : 4, + "frequencies" : { + "usa" : 2, + "hello": 3, + "world": 5, + "test": 2 + } +} diff --git a/container-search/src/test/java/com/yahoo/search/significance/test/SignificanceSearcherTest.java b/container-search/src/test/java/com/yahoo/search/significance/test/SignificanceSearcherTest.java new file mode 100644 index 00000000000..890db3abb51 --- /dev/null +++ b/container-search/src/test/java/com/yahoo/search/significance/test/SignificanceSearcherTest.java @@ -0,0 +1,153 @@ +// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.search.significance.test; + +import com.yahoo.component.chain.Chain; +import com.yahoo.language.Language; +import com.yahoo.language.significance.SignificanceModel; +import com.yahoo.language.significance.SignificanceModelRegistry; +import com.yahoo.language.significance.impl.DefaultSignificanceModelRegistry; +import com.yahoo.prelude.query.AndItem; +import com.yahoo.prelude.query.WordItem; +import com.yahoo.search.Query; +import com.yahoo.search.Result; +import com.yahoo.search.searchchain.Execution; +import com.yahoo.search.significance.SignificanceSearcher; +import org.junit.jupiter.api.Test; + +import java.nio.file.Path; +import java.util.HashMap; + + +import static com.yahoo.test.JunitCompat.assertEquals; + +/** + * Tests significance term in the search chain. + * + * @author MariusArhaug + */ +public class SignificanceSearcherTest { + SignificanceModelRegistry significanceModelRegistry; + SignificanceSearcher searcher; + + public SignificanceSearcherTest() { + HashMap<Language, Path> map = new HashMap<>(); + map.put(Language.ENGLISH, Path.of("src/test/java/com/yahoo/search/significance/model/en.json")); + + significanceModelRegistry = new DefaultSignificanceModelRegistry(map); + searcher = new SignificanceSearcher(significanceModelRegistry); + } + + private Execution createExecution(SignificanceSearcher searcher) { + return new Execution(new Chain<>(searcher), Execution.Context.createContextStub()); + } + + private Execution createExecution() { + return new Execution(new Chain<>(), Execution.Context.createContextStub()); + } + + @Test + void testSignificanceValueOnSimpleQuery() { + + Query q = new Query(); + AndItem root = new AndItem(); + WordItem tmp; + tmp = new WordItem("Hello", true); + root.addItem(tmp); + tmp = new WordItem("world", true); + root.addItem(tmp); + + q.getModel().getQueryTree().setRoot(root); + + SignificanceModel model = significanceModelRegistry.getModel(Language.ENGLISH).get(); + var helloFrequency = model.documentFrequency("Hello"); + var helloSignificanceValue = SignificanceSearcher.calculateIDF(helloFrequency.corpusSize(), helloFrequency.frequency()); + + var worldFrequency = model.documentFrequency("world"); + var worldSignificanceValue = SignificanceSearcher.calculateIDF(worldFrequency.corpusSize(), worldFrequency.frequency()); + + Result r = createExecution(searcher).search(q); + + root = (AndItem) r.getQuery().getModel().getQueryTree().getRoot(); + WordItem w0 = (WordItem) root.getItem(0); + WordItem w1 = (WordItem) root.getItem(1); + + assertEquals(helloSignificanceValue, w0.getSignificance()); + assertEquals(worldSignificanceValue, w1.getSignificance()); + + } + + @Test + void testSignificanceValueOnRecursiveQuery() { + Query q = new Query(); + AndItem root = new AndItem(); + WordItem child1 = new WordItem("hello", true); + + AndItem child2 = new AndItem(); + WordItem child2_1 = new WordItem("test", true); + + AndItem child3 = new AndItem(); + AndItem child3_1 = new AndItem(); + WordItem child3_1_1 = new WordItem("usa", true); + + root.addItem(child1); + root.addItem(child2); + root.addItem(child3); + + child2.addItem(child2_1); + child3.addItem(child3_1); + child3_1.addItem(child3_1_1); + + q.getModel().getQueryTree().setRoot(root); + + SignificanceModel model = significanceModelRegistry.getModel(Language.ENGLISH).get(); + var helloFrequency = model.documentFrequency("hello"); + var helloSignificanceValue = SignificanceSearcher.calculateIDF(helloFrequency.corpusSize(), helloFrequency.frequency()); + + var testFrequency = model.documentFrequency("test"); + var testSignificanceValue = SignificanceSearcher.calculateIDF(testFrequency.corpusSize(), testFrequency.frequency()); + + + + Result r = createExecution(searcher).search(q); + + root = (AndItem) r.getQuery().getModel().getQueryTree().getRoot(); + WordItem w0 = (WordItem) root.getItem(0); + WordItem w1 = (WordItem) ((AndItem) root.getItem(1)).getItem(0); + WordItem w3 = (WordItem) ((AndItem) ((AndItem) root.getItem(2)).getItem(0)).getItem(0); + + assertEquals(helloSignificanceValue, w0.getSignificance()); + assertEquals(testSignificanceValue, w1.getSignificance()); + assertEquals(SignificanceSearcher.calculateIDF(10, 2), w3.getSignificance()); + + } + + @Test + void testSignificanceValueOnEmptyQuery() { + Query q = new Query(); + q.getModel().setLanguage(Language.NORWEGIAN_BOKMAL); + AndItem root = new AndItem(); + WordItem tmp; + tmp = new WordItem("Hei", true); + root.addItem(tmp); + tmp = new WordItem("Verden", true); + root.addItem(tmp); + + + q.getModel().getQueryTree().setRoot(root); + Result r = createExecution(searcher).search(q); + root = (AndItem) r.getQuery().getModel().getQueryTree().getRoot(); + + WordItem w0 = (WordItem) root.getItem(0); + WordItem w1 = (WordItem) root.getItem(1); + + Result r0 = createExecution().search(q); + root = (AndItem) r0.getQuery().getModel().getQueryTree().getRoot(); + + WordItem w0_0 = (WordItem) root.getItem(0); + WordItem w0_1 = (WordItem) root.getItem(1); + + assertEquals(w0_0.getSignificance(), w0.getSignificance()); + assertEquals(w0_1.getSignificance(), w1.getSignificance()); + + } +} diff --git a/dependency-versions/pom.xml b/dependency-versions/pom.xml index e34ccddf8e3..10aa71c1d90 100644 --- a/dependency-versions/pom.xml +++ b/dependency-versions/pom.xml @@ -68,8 +68,8 @@ <assertj.vespa.version>3.25.3</assertj.vespa.version> <!-- Athenz dependencies. Make sure these dependencies match those in Vespa's internal repositories --> - <aws-sdk.vespa.version>1.12.706</aws-sdk.vespa.version> - <athenz.vespa.version>1.11.56</athenz.vespa.version> + <aws-sdk.vespa.version>1.12.708</aws-sdk.vespa.version> + <athenz.vespa.version>1.11.57</athenz.vespa.version> <!-- Athenz END --> <!-- WARNING: If you change curator version, you also need to update @@ -79,7 +79,7 @@ xargs perl -pi -e 's/major = [0-9]+, minor = [0-9]+, micro = [0-9]+/major = 5, minor = 3, micro = 0/g' --> <bouncycastle.vespa.version>1.78.1</bouncycastle.vespa.version> - <byte-buddy.vespa.version>1.14.13</byte-buddy.vespa.version> + <byte-buddy.vespa.version>1.14.14</byte-buddy.vespa.version> <checker-qual.vespa.version>3.38.0</checker-qual.vespa.version> <commons-beanutils.vespa.version>1.9.4</commons-beanutils.vespa.version> <commons-codec.vespa.version>1.16.1</commons-codec.vespa.version> @@ -118,7 +118,7 @@ <junit.platform.vespa.version>1.10.2</junit.platform.vespa.version> <junit4.vespa.version>4.13.2</junit4.vespa.version> <kherud.llama.vespa.version>3.0.0</kherud.llama.vespa.version> - <luben.zstd.vespa.version>1.5.6-2</luben.zstd.vespa.version> + <luben.zstd.vespa.version>1.5.6-3</luben.zstd.vespa.version> <lucene.vespa.version>9.10.0</lucene.vespa.version> <maven-archiver.vespa.version>3.6.2</maven-archiver.vespa.version> <maven-wagon.vespa.version>3.5.3</maven-wagon.vespa.version> @@ -129,7 +129,7 @@ <netty.vespa.version>4.1.109.Final</netty.vespa.version> <netty-tcnative.vespa.version>2.0.65.Final</netty-tcnative.vespa.version> <onnxruntime.vespa.version>1.17.1</onnxruntime.vespa.version> - <opennlp.vespa.version>2.3.2</opennlp.vespa.version> + <opennlp.vespa.version>2.3.3</opennlp.vespa.version> <opentest4j.vespa.version>1.3.0</opentest4j.vespa.version> <org.json.vespa.version>20240303</org.json.vespa.version> <org.lz4.vespa.version>1.8.0</org.lz4.vespa.version> @@ -182,7 +182,7 @@ <maven-plugin-tools.vespa.version>3.12.0</maven-plugin-tools.vespa.version> <maven-resources-plugin.vespa.version>3.3.1</maven-resources-plugin.vespa.version> <maven-resolver.vespa.version>1.9.19</maven-resolver.vespa.version> - <maven-shade-plugin.vespa.version>3.5.2</maven-shade-plugin.vespa.version> + <maven-shade-plugin.vespa.version>3.5.3</maven-shade-plugin.vespa.version> <maven-site-plugin.vespa.version>3.12.1</maven-site-plugin.vespa.version> <maven-source-plugin.vespa.version>3.3.1</maven-source-plugin.vespa.version> <properties-maven-plugin.vespa.version>1.2.1</properties-maven-plugin.vespa.version> diff --git a/document/src/main/java/com/yahoo/document/json/JsonReader.java b/document/src/main/java/com/yahoo/document/json/JsonReader.java index b6cf8c6e18b..358c0cb65e4 100644 --- a/document/src/main/java/com/yahoo/document/json/JsonReader.java +++ b/document/src/main/java/com/yahoo/document/json/JsonReader.java @@ -30,7 +30,7 @@ import static com.yahoo.document.json.readers.JsonParserHelpers.expectArrayStart * valid JSON representation of a feed. * * @author Steinar Knutsen - * @author dybis + * @author Haakon Dybdahl */ public class JsonReader { diff --git a/eval/src/tests/eval/typed_cells/typed_cells_test.cpp b/eval/src/tests/eval/typed_cells/typed_cells_test.cpp index f4171937ce3..53e0f7c84d3 100644 --- a/eval/src/tests/eval/typed_cells/typed_cells_test.cpp +++ b/eval/src/tests/eval/typed_cells/typed_cells_test.cpp @@ -1,39 +1,13 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/eval/eval/typed_cells.h> #include <vespa/vespalib/testkit/test_kit.h> -#include <vespa/vespalib/util/arrayref.h> #include <memory> using namespace vespalib; +using namespace eval; -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// Low-level typed cells reference -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -enum class CellType : char { DOUBLE, FLOAT, INT }; -template <typename T> bool check_type(CellType type); -template <> bool check_type<double>(CellType type) { return (type == CellType::DOUBLE); } -template <> bool check_type<float>(CellType type) { return (type == CellType::FLOAT); } -template <> bool check_type<int>(CellType type) { return (type == CellType::INT); } - -struct TypedCells { - const void *data; - CellType type; - size_t size:56; - explicit TypedCells(ConstArrayRef<double> cells) : data(cells.begin()), type(CellType::DOUBLE), size(cells.size()) {} - explicit TypedCells(ConstArrayRef<float> cells) : data(cells.begin()), type(CellType::FLOAT), size(cells.size()) {} - explicit TypedCells(ConstArrayRef<int> cells) : data(cells.begin()), type(CellType::INT), size(cells.size()) {} - template <typename T> bool check_type() const { return ::check_type<T>(type); } - template <typename T> ConstArrayRef<T> typify() const { - assert(check_type<T>()); - return ConstArrayRef<T>((const T *)data, size); - } - template <typename T> ConstArrayRef<T> unsafe_typify() const { - return ConstArrayRef<T>((const T *)data, size); - } -}; TEST("require that structures are of expected size") { EXPECT_EQUAL(sizeof(void*), 8u); @@ -102,27 +76,27 @@ struct Typify { switch(a.type) { case CellType::DOUBLE: return T::call(a.unsafe_typify<double>(), std::forward<Args>(args)...); case CellType::FLOAT: return T::call(a.unsafe_typify<float>(), std::forward<Args>(args)...); - case CellType::INT: return T::call(a.unsafe_typify<int>(), std::forward<Args>(args)...); + case CellType::INT8: return T::call(a.unsafe_typify<Int8Float>(), std::forward<Args>(args)...); + default: abort(); } - abort(); } template <typename A, typename... Args> static auto typify_2(A &&a, const TypedCells &b, Args &&...args) { switch(b.type) { case CellType::DOUBLE: return T::call(std::forward<A>(a), b.unsafe_typify<double>(), std::forward<Args>(args)...); case CellType::FLOAT: return T::call(std::forward<A>(a), b.unsafe_typify<float>(), std::forward<Args>(args)...); - case CellType::INT: return T::call(std::forward<A>(a), b.unsafe_typify<int>(), std::forward<Args>(args)...); + case CellType::INT8: return T::call(std::forward<A>(a), b.unsafe_typify<Int8Float>(), std::forward<Args>(args)...); + default: abort(); } - abort(); } template <typename A, typename B, typename... Args> static auto typify_3(A &&a, B &&b, const TypedCells &c, Args &&...args) { switch(c.type) { case CellType::DOUBLE: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<double>(), std::forward<Args>(args)...); case CellType::FLOAT: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<float>(), std::forward<Args>(args)...); - case CellType::INT: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<int>(), std::forward<Args>(args)...); + case CellType::INT8: return T::call(std::forward<A>(a), std::forward<B>(b), c.unsafe_typify<Int8Float>(), std::forward<Args>(args)...); + default: abort(); } - abort(); } }; @@ -200,15 +174,15 @@ struct Dispatch1 { //----------------------------------------------------------------------------- TEST("require that direct dispatch 'a op b -> c' works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - std::vector<double> c(3, 0.0); - ConstArrayRef<int> a_ref(a); - ConstArrayRef<float> b_ref(b); - ConstArrayRef<double> c_ref(c); - TypedCells a_cells(a); - TypedCells b_cells(b); - TypedCells c_cells(c); + std::vector<Int8Float> a({1,2,3}); + std::vector<float> b({1.5,2.5,3.5}); + std::vector<double> c(3, 0.0); + ConstArrayRef<Int8Float> a_ref(a); + ConstArrayRef<float> b_ref(b); + ConstArrayRef<double> c_ref(c); + TypedCells a_cells(a); + TypedCells b_cells(b); + TypedCells c_cells(c); Dispatch3<CellwiseAdd>::call(a_cells, b_cells, c_cells, 3); Dispatch3<CellwiseAdd>::call(a_cells, b_ref, c_cells, 3); @@ -225,13 +199,13 @@ TEST("require that direct dispatch 'a op b -> c' works") { } TEST("require that direct dispatch 'dot product' with return value works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - ConstArrayRef<int> a_ref(a); - ConstArrayRef<float> b_ref(b); - TypedCells a_cells(a); - TypedCells b_cells(b); - double expect = 1.5 + (2 * 2.5) + (3 * 3.5); + std::vector<Int8Float> a({1,2,3}); + std::vector<float> b({1.5,2.5,3.5}); + ConstArrayRef<Int8Float> a_ref(a); + ConstArrayRef<float> b_ref(b); + TypedCells a_cells(a); + TypedCells b_cells(b); + double expect = 1.5 + (2 * 2.5) + (3 * 3.5); EXPECT_EQUAL(expect, Dispatch2<DotProduct>::call(a_cells, b_cells, 3)); EXPECT_EQUAL(expect, Dispatch2<DotProduct>::call(a_cells, b_ref, 3)); @@ -240,10 +214,10 @@ TEST("require that direct dispatch 'dot product' with return value works") { } TEST("require that direct dispatch 'sum' with return value works") { - std::vector<int> a({1,2,3}); - ConstArrayRef<int> a_ref(a); - TypedCells a_cells(a); - double expect = (1 + 2 + 3); + std::vector<Int8Float> a({1,2,3}); + ConstArrayRef<Int8Float> a_ref(a); + TypedCells a_cells(a); + double expect = (1 + 2 + 3); EXPECT_EQUAL(expect, Dispatch1<Sum>::call(a_cells)); EXPECT_EQUAL(expect, Dispatch1<Sum>::call(a_ref)); @@ -259,7 +233,7 @@ struct CellwiseAdd2 { virtual void call(const TypedCells &a, const TypedCells &b, const TypedCells &c, size_t cnt) const = 0; template <typename A, typename B, typename C> static std::unique_ptr<CellwiseAdd2> create(); - virtual ~CellwiseAdd2() {} + virtual ~CellwiseAdd2() = default; }; template <typename A, typename B, typename C> @@ -286,7 +260,7 @@ struct DotProduct2 { virtual double call(const TypedCells &a, const TypedCells &b, size_t cnt) const = 0; template <typename A, typename B> static std::unique_ptr<DotProduct2> create(); - virtual ~DotProduct2() {} + virtual ~DotProduct2() = default; }; template <typename A, typename B> @@ -314,7 +288,7 @@ struct Sum2 { virtual double call(const TypedCells &a) const = 0; template <typename A> static std::unique_ptr<Sum2> create(); - virtual ~Sum2() {} + virtual ~Sum2() = default; }; template <typename A> @@ -343,9 +317,9 @@ std::unique_ptr<T> create(CellType a_type) { switch(a_type) { case CellType::DOUBLE: return T::template create<double, Args...>(); case CellType::FLOAT: return T::template create<float, Args...>(); - case CellType::INT: return T::template create<int, Args...>(); + case CellType::INT8: return T::template create<Int8Float, Args...>(); + default: abort(); } - abort(); } template <typename T, typename... Args> @@ -353,9 +327,9 @@ std::unique_ptr<T> create(CellType a_type, CellType b_type) { switch(b_type) { case CellType::DOUBLE: return create<T, double, Args...>(a_type); case CellType::FLOAT: return create<T, float, Args...>(a_type); - case CellType::INT: return create<T, int, Args...>(a_type); + case CellType::INT8: return create<T, Int8Float, Args...>(a_type); + default: abort(); } - abort(); } template <typename T> @@ -363,20 +337,20 @@ std::unique_ptr<T> create(CellType a_type, CellType b_type, CellType c_type) { switch(c_type) { case CellType::DOUBLE: return create<T, double>(a_type, b_type); case CellType::FLOAT: return create<T, float>(a_type, b_type); - case CellType::INT: return create<T, int>(a_type, b_type); + case CellType::INT8: return create<T, Int8Float>(a_type, b_type); + default: abort(); } - abort(); } //----------------------------------------------------------------------------- TEST("require that pre-resolved subclass 'a op b -> c' works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - std::vector<double> c(3, 0.0); - TypedCells a_cells(a); - TypedCells b_cells(b); - TypedCells c_cells(c); + std::vector<Int8Float> a({1,2,3}); + std::vector<float> b({1.5,2.5,3.5}); + std::vector<double> c(3, 0.0); + TypedCells a_cells(a); + TypedCells b_cells(b); + TypedCells c_cells(c); auto op = create<CellwiseAdd2>(a_cells.type, b_cells.type, c_cells.type); op->call(a_cells, b_cells, c_cells, 3); @@ -387,11 +361,11 @@ TEST("require that pre-resolved subclass 'a op b -> c' works") { } TEST("require that pre-resolved subclass 'dot product' with return value works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - TypedCells a_cells(a); - TypedCells b_cells(b); - double expect = 1.5 + (2 * 2.5) + (3 * 3.5); + std::vector<Int8Float> a({1,2,3}); + std::vector<float> b({1.5,2.5,3.5}); + TypedCells a_cells(a); + TypedCells b_cells(b); + double expect = 1.5 + (2 * 2.5) + (3 * 3.5); auto op = create<DotProduct2>(a_cells.type, b_cells.type); @@ -399,9 +373,9 @@ TEST("require that pre-resolved subclass 'dot product' with return value works") } TEST("require that pre-resolved subclass 'sum' with return value works") { - std::vector<int> a({1,2,3}); - TypedCells a_cells(a); - double expect = (1 + 2 + 3); + std::vector<Int8Float> a({1,2,3}); + TypedCells a_cells(a); + double expect = (1 + 2 + 3); auto op = create<Sum2>(a_cells.type); @@ -419,9 +393,9 @@ auto get_fun(CellType a_type) { switch(a_type) { case CellType::DOUBLE: return T::template get_fun<double, Args...>(); case CellType::FLOAT: return T::template get_fun<float, Args...>(); - case CellType::INT: return T::template get_fun<int, Args...>(); + case CellType::INT8: return T::template get_fun<Int8Float, Args...>(); + default: abort(); } - abort(); } template <typename T, typename... Args> @@ -429,9 +403,9 @@ auto get_fun(CellType a_type, CellType b_type) { switch(b_type) { case CellType::DOUBLE: return get_fun<T, double, Args...>(a_type); case CellType::FLOAT: return get_fun<T, float, Args...>(a_type); - case CellType::INT: return get_fun<T, int, Args...>(a_type); + case CellType::INT8: return get_fun<T, Int8Float, Args...>(a_type); + default: abort(); } - abort(); } template <typename T> @@ -439,9 +413,9 @@ auto get_fun(CellType a_type, CellType b_type, CellType c_type) { switch(c_type) { case CellType::DOUBLE: return get_fun<T, double>(a_type, b_type); case CellType::FLOAT: return get_fun<T, float>(a_type, b_type); - case CellType::INT: return get_fun<T, int>(a_type, b_type); + case CellType::INT8: return get_fun<T, Int8Float>(a_type, b_type); + default: abort(); } - abort(); } //----------------------------------------------------------------------------- @@ -575,17 +549,17 @@ Sum3::Self::Self() //----------------------------------------------------------------------------- TEST("require that self-updating cached function pointer 'a op b -> c' works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - std::vector<double> c(3, 0.0); - TypedCells a_cells(a); - TypedCells b_cells(b); - TypedCells c_cells(c); + std::vector<Int8Float> a({1,2,3}); + std::vector<float> b({1.5,2.5,3.5}); + std::vector<double> c(3, 0.0); + TypedCells a_cells(a); + TypedCells b_cells(b); + TypedCells c_cells(c); CellwiseAdd3 op; EXPECT_EQUAL(op.self.my_fun, (&cellwise_add<double,double,double>)); op.call(a_cells, b_cells, c_cells, 3); - EXPECT_EQUAL(op.self.my_fun, (&cellwise_add<int,float,double>)); + EXPECT_EQUAL(op.self.my_fun, (&cellwise_add<Int8Float,float,double>)); EXPECT_NOT_EQUAL(op.self.my_fun, (&cellwise_add<double,double,double>)); EXPECT_EQUAL(c[0], 2.5); @@ -594,29 +568,40 @@ TEST("require that self-updating cached function pointer 'a op b -> c' works") { } TEST("require that self-updating cached function pointer 'dot product' with return value works") { - std::vector<int> a({1,2,3}); - std::vector<float> b({1.5,2.5,3.5}); - TypedCells a_cells(a); - TypedCells b_cells(b); - double expect = 1.5 + (2 * 2.5) + (3 * 3.5); + std::vector<Int8Float> a({1,2,3}); + std::vector<float> b({1.5,2.5,3.5}); + TypedCells a_cells(a); + TypedCells b_cells(b); + double expect = 1.5 + (2 * 2.5) + (3 * 3.5); DotProduct3 op; EXPECT_EQUAL(op.self.my_fun, (&dot_product<double,double>)); EXPECT_EQUAL(expect, op.call(a_cells, b_cells, 3)); - EXPECT_EQUAL(op.self.my_fun, (&dot_product<int,float>)); + EXPECT_EQUAL(op.self.my_fun, (&dot_product<Int8Float,float>)); EXPECT_NOT_EQUAL(op.self.my_fun, (&dot_product<double,double>)); } TEST("require that self-updating cached function pointer 'sum' with return value works") { - std::vector<int> a({1,2,3}); - TypedCells a_cells(a); - double expect = (1 + 2 + 3); + std::vector<Int8Float> a({1,2,3}); + TypedCells a_cells(a); + double expect = (1 + 2 + 3); Sum3 op; EXPECT_EQUAL(op.self.my_fun, (&sum<double>)); EXPECT_EQUAL(expect, op.call(a_cells)); - EXPECT_EQUAL(op.self.my_fun, (&sum<int>)); + EXPECT_EQUAL(op.self.my_fun, (&sum<Int8Float>)); EXPECT_NOT_EQUAL(op.self.my_fun, (&sum<double>)); } +TEST("require that non_existing_attribute_value can be controlled") { + float values[3] = {0,1,2}; + EXPECT_FALSE(TypedCells().non_existing_attribute_value()); + EXPECT_FALSE(TypedCells(values, CellType::FLOAT, 3).non_existing_attribute_value()); + EXPECT_FALSE(TypedCells(ConstArrayRef<double>()).non_existing_attribute_value()); + EXPECT_FALSE(TypedCells(ConstArrayRef<float>()).non_existing_attribute_value()); + EXPECT_FALSE(TypedCells(ConstArrayRef<Int8Float>()).non_existing_attribute_value()); + EXPECT_FALSE(TypedCells(ConstArrayRef<BFloat16>()).non_existing_attribute_value()); + EXPECT_TRUE(TypedCells::create_non_existing_attribute_value(values, CellType::FLOAT, 3).non_existing_attribute_value()); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/eval/src/vespa/eval/eval/typed_cells.h b/eval/src/vespa/eval/eval/typed_cells.h index 3dd8c30a3a9..fa3b0ca150d 100644 --- a/eval/src/vespa/eval/eval/typed_cells.h +++ b/eval/src/vespa/eval/eval/typed_cells.h @@ -11,16 +11,23 @@ namespace vespalib::eval { struct TypedCells { const void *data; - size_t size:56; + size_t size:55; + bool _non_existing_attribute_value:1; CellType type; - explicit TypedCells(ConstArrayRef<double> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::DOUBLE) {} - explicit TypedCells(ConstArrayRef<float> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::FLOAT) {} - explicit TypedCells(ConstArrayRef<BFloat16> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::BFLOAT16) {} - explicit TypedCells(ConstArrayRef<Int8Float> cells) noexcept : data(cells.begin()), size(cells.size()), type(CellType::INT8) {} + explicit TypedCells(ConstArrayRef<double> cells) noexcept : data(cells.begin()), size(cells.size()), _non_existing_attribute_value(false), type(CellType::DOUBLE) {} + explicit TypedCells(ConstArrayRef<float> cells) noexcept : data(cells.begin()), size(cells.size()), _non_existing_attribute_value(false), type(CellType::FLOAT) {} + explicit TypedCells(ConstArrayRef<BFloat16> cells) noexcept : data(cells.begin()), size(cells.size()), _non_existing_attribute_value(false), type(CellType::BFLOAT16) {} + explicit TypedCells(ConstArrayRef<Int8Float> cells) noexcept : data(cells.begin()), size(cells.size()), _non_existing_attribute_value(false), type(CellType::INT8) {} - TypedCells() noexcept : data(nullptr), size(0), type(CellType::DOUBLE) {} - TypedCells(const void *dp, CellType ct, size_t sz) noexcept : data(dp), size(sz), type(ct) {} + TypedCells() noexcept : data(nullptr), size(0), _non_existing_attribute_value(false), type(CellType::DOUBLE) {} + TypedCells(const void *dp, CellType ct, size_t sz) noexcept : data(dp), size(sz), _non_existing_attribute_value(false), type(ct) {} + + static TypedCells create_non_existing_attribute_value(const void *dp, CellType ct, size_t sz) { + TypedCells cells(dp, ct, sz); + cells._non_existing_attribute_value = true; + return cells; + } template <typename T> bool check_type() const noexcept { return check_cell_type<T>(type); } @@ -36,7 +43,13 @@ struct TypedCells { TypedCells(const TypedCells &other) noexcept = default; TypedCells & operator= (TypedCells &&other) noexcept = default; TypedCells & operator= (const TypedCells &other) noexcept = default; - bool valid() const noexcept { return size != 0; } + /** + * This signals that this actually points to a value that is the default value + * when no value has set for the attribute. + * TODO: This does not belong here, but as it is used as an interface multiple places it must be so + * until we come up with a better solution. + */ + bool non_existing_attribute_value() const noexcept { return _non_existing_attribute_value; } }; } // namespace diff --git a/eval/src/vespa/eval/onnx/onnx_wrapper.cpp b/eval/src/vespa/eval/onnx/onnx_wrapper.cpp index 5457a3a1d1c..e5924043a8c 100644 --- a/eval/src/vespa/eval/onnx/onnx_wrapper.cpp +++ b/eval/src/vespa/eval/onnx/onnx_wrapper.cpp @@ -163,7 +163,7 @@ class OnnxString { private: static Ort::AllocatorWithDefaultOptions _alloc; Ort::AllocatedStringPtr _str; - OnnxString(Ort::AllocatedStringPtr str) : _str(std::move(str)) {} + OnnxString(Ort::AllocatedStringPtr str) noexcept : _str(std::move(str)) {} public: OnnxString(const OnnxString &rhs) = delete; OnnxString &operator=(const OnnxString &rhs) = delete; diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java index 400934fce97..a3fe010c65b 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java @@ -84,6 +84,18 @@ public class Flags { "Takes effect at redeployment", INSTANCE_ID); + public static final UnboundBooleanFlag NEW_RESOURCES_FORMULA = defineFeatureFlag( + "new-resources-formula", true, + List.of("hakonhall"), "2024-04-25", "2024-05-25", + "Use an easier to understand formula for calculating the memory and disk resources", + "Takes effect on next deployment of an applications."); + + public static final UnboundBooleanFlag FIX_CONFIG_SERVER_HEAP = defineFeatureFlag( + "fix-config-server-heap", false, + List.of("hakonhall"), "2024-04-23", "2024-05-23", + "Base the calculation of the config server JVM heap size on the amount of memory available to the container.", + "Takes effect on start of config server Podman container"); + public static final UnboundStringFlag RESPONSE_SEQUENCER_TYPE = defineStringFlag( "response-sequencer-type", "ADAPTIVE", List.of("baldersheim"), "2020-12-02", "2024-12-31", @@ -422,12 +434,6 @@ public class Flags { "Role definitions for the system", "Takes effect immediately"); - public static UnboundBooleanFlag NEW_PATH_FOR_DISK_ENCRYPTION_KEY_METADATA = defineFeatureFlag( - "new-path-for-disk-encryption-key-metadata", true, - List.of("hmusum"), "2024-04-08", "2024-06-01", - "Whether to read and write disk encryption key to new path", - "Will be read only on boot."); - public static final UnboundIntFlag PERSISTENCE_THREAD_MAX_FEED_OP_BATCH_SIZE = defineIntFlag( "persistence-thread-max-feed-op-batch-size", 1, List.of("vekterli"), "2024-04-12", "2025-01-01", diff --git a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java index ad9f4c6a7ab..3b73d9d6013 100644 --- a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java +++ b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java @@ -410,6 +410,11 @@ public class PermanentFlags { "triggered", "Takes effect immediately"); + public static final UnboundIntFlag MAX_CERTIFICATES_PER_HOUR = defineIntFlag( + "max-certificates-per-hour", 10, + "The number of certificates can be provisioned per hour, before throttling is triggered", + "Takes effect immediately"); + public static final UnboundBooleanFlag DROP_CACHES = defineFeatureFlag( "drop-caches", true, "Drop pagecache. " + diff --git a/linguistics/abi-spec.json b/linguistics/abi-spec.json index a4adacc5905..1ca32a2dd37 100644 --- a/linguistics/abi-spec.json +++ b/linguistics/abi-spec.json @@ -816,7 +816,7 @@ "abstract" ], "methods" : [ - "public abstract com.yahoo.language.significance.SignificanceModel getModel(com.yahoo.language.Language)" + "public abstract java.util.Optional getModel(com.yahoo.language.Language)" ], "fields" : [ ] } diff --git a/linguistics/src/main/java/com/yahoo/language/significance/SignificanceModelRegistry.java b/linguistics/src/main/java/com/yahoo/language/significance/SignificanceModelRegistry.java index 6d8dcc00e0a..95d5b5e69d8 100644 --- a/linguistics/src/main/java/com/yahoo/language/significance/SignificanceModelRegistry.java +++ b/linguistics/src/main/java/com/yahoo/language/significance/SignificanceModelRegistry.java @@ -4,10 +4,12 @@ package com.yahoo.language.significance; import com.yahoo.api.annotations.Beta; import com.yahoo.language.Language; +import java.util.Optional; + /** * @author MariusArhaug */ @Beta public interface SignificanceModelRegistry { - SignificanceModel getModel(Language language); + Optional<SignificanceModel> getModel(Language language); } diff --git a/linguistics/src/main/java/com/yahoo/language/significance/impl/DefaultSignificanceModelRegistry.java b/linguistics/src/main/java/com/yahoo/language/significance/impl/DefaultSignificanceModelRegistry.java index d44eab39cdf..1be1d3f13b5 100644 --- a/linguistics/src/main/java/com/yahoo/language/significance/impl/DefaultSignificanceModelRegistry.java +++ b/linguistics/src/main/java/com/yahoo/language/significance/impl/DefaultSignificanceModelRegistry.java @@ -11,6 +11,7 @@ import java.nio.file.Path; import java.util.EnumMap; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.function.Supplier; import static com.yahoo.yolean.Exceptions.uncheck; @@ -43,12 +44,12 @@ public class DefaultSignificanceModelRegistry implements SignificanceModelRegist @Override - public SignificanceModel getModel(Language language) throws IllegalArgumentException { + public Optional<SignificanceModel> getModel(Language language) { if (!models.containsKey(language)) { - throw new IllegalArgumentException("No model for language " + language); + return Optional.empty(); } - return models.get(language); + return Optional.of(models.get(language)); } diff --git a/linguistics/src/test/java/com/yahoo/language/significance/DefaultSignificanceModelRegistryTest.java b/linguistics/src/test/java/com/yahoo/language/significance/DefaultSignificanceModelRegistryTest.java index d1de63a994d..d4849571b5e 100644 --- a/linguistics/src/test/java/com/yahoo/language/significance/DefaultSignificanceModelRegistryTest.java +++ b/linguistics/src/test/java/com/yahoo/language/significance/DefaultSignificanceModelRegistryTest.java @@ -8,9 +8,7 @@ import org.junit.Test; import java.nio.file.Path; import java.util.HashMap; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.*; /** @@ -27,10 +25,16 @@ public class DefaultSignificanceModelRegistryTest { DefaultSignificanceModelRegistry defaultSignificanceModelRegistry = new DefaultSignificanceModelRegistry(models); - var englishModel = defaultSignificanceModelRegistry.getModel(Language.ENGLISH); - var norwegianModel = defaultSignificanceModelRegistry.getModel(Language.NORWEGIAN_BOKMAL); + var optionalEnglishModel = defaultSignificanceModelRegistry.getModel(Language.ENGLISH); + var optionalNorwegianModel = defaultSignificanceModelRegistry.getModel(Language.NORWEGIAN_BOKMAL); - assertThrows(IllegalArgumentException.class, () -> defaultSignificanceModelRegistry.getModel(Language.FRENCH)); + assertTrue(optionalEnglishModel.isPresent()); + assertTrue(optionalNorwegianModel.isPresent()); + + var englishModel = optionalEnglishModel.get(); + var norwegianModel = optionalNorwegianModel.get(); + + assertTrue( defaultSignificanceModelRegistry.getModel(Language.FRENCH).isEmpty()); assertNotNull(englishModel); assertNotNull(norwegianModel); diff --git a/messagebus/src/main/java/com/yahoo/messagebus/AllPassThrottlePolicy.java b/messagebus/src/main/java/com/yahoo/messagebus/AllPassThrottlePolicy.java index 4835aad5a27..7316645b5c9 100644 --- a/messagebus/src/main/java/com/yahoo/messagebus/AllPassThrottlePolicy.java +++ b/messagebus/src/main/java/com/yahoo/messagebus/AllPassThrottlePolicy.java @@ -4,7 +4,7 @@ package com.yahoo.messagebus; /** * This is an implementation of the {@link ThrottlePolicy} that passes all requests (no real throttling). * - * @author dybis + * @author Haakon Dybdahl */ public class AllPassThrottlePolicy implements ThrottlePolicy { diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java index 60e85f3f9e4..1bc00c448c8 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/MetricsManager.java @@ -152,7 +152,7 @@ public class MetricsManager { static MetricsPacket.Builder adjustTimestamp(MetricsPacket.Builder builder, Instant startTime) { Duration age = Duration.between(startTime, builder.getTimestamp()); if (age.abs().minusMinutes(1).isNegative()) - builder.timestamp(startTime.getEpochSecond()); + builder.timestamp(startTime); return builder; } diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/VespaMetrics.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/VespaMetrics.java index 4dabc7a66d8..2edb67b73ab 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/VespaMetrics.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/core/VespaMetrics.java @@ -104,7 +104,7 @@ public class VespaMetrics { private MetricsPacket.Builder getHealth(VespaService service) { HealthMetric health = service.getHealth(); return new MetricsPacket.Builder(service.getMonitoringName()) - .timestamp(System.currentTimeMillis() / 1000) + .timestamp(Instant.now()) .statusCode(health.getStatus().ordinal()) // TODO: MetricsPacket should use StatusCode instead of int .statusMessage(health.getMessage()) .putDimensions(service.getDimensions()) @@ -228,7 +228,7 @@ public class VespaMetrics { } private static void setMetaInfo(MetricsPacket.Builder builder, Instant timestamp) { - builder.timestamp(timestamp.getEpochSecond()) + builder.timestamp(timestamp) .statusCode(0) .statusMessage("Data collected successfully"); } diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/MetricsPacket.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/MetricsPacket.java index fb08d78a975..c1440bf890a 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/MetricsPacket.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/MetricsPacket.java @@ -27,15 +27,15 @@ import static java.util.stream.Collectors.joining; */ public class MetricsPacket { - public final int statusCode; - public final String statusMessage; - public final long timestamp; - public final ServiceId service; + private final int statusCode; + private final String statusMessage; + private final ServiceId service; + private final Instant timestamp; private final Map<MetricId, Number> metrics; private final Map<DimensionId, String> dimensions; private final Set<ConsumerId> consumers; - private MetricsPacket(int statusCode, String statusMessage, long timestamp, ServiceId service, + private MetricsPacket(int statusCode, String statusMessage, Instant timestamp, ServiceId service, Map<MetricId, Number> metrics, Map<DimensionId, String> dimensions, Set<ConsumerId> consumers ) { this.statusCode = statusCode; this.statusMessage = statusMessage; @@ -48,7 +48,11 @@ public class MetricsPacket { public Map<MetricId, Number> metrics() { return metrics; } public Map<DimensionId, String> dimensions() { return dimensions; } - public Set<ConsumerId> consumers() { return consumers;} + public Set<ConsumerId> consumers() { return consumers; } + public Instant timestamp() { return timestamp; } + public ServiceId service() { return service; } + public int statusCode() { return statusCode; } + public String statusMessage() { return statusMessage; } @Override public String toString() { @@ -76,7 +80,7 @@ public class MetricsPacket { private ServiceId service; private int statusCode = 0; private String statusMessage = ""; - private long timestamp = 0L; + private Instant timestamp = Instant.EPOCH; private Map<MetricId, Number> metrics = new LinkedHashMap<>(); private final Map<DimensionId, String> dimensions = new LinkedHashMap<>(); private Set<ConsumerId> consumers = Set.of(); @@ -102,7 +106,7 @@ public class MetricsPacket { return this; } - public Builder timestamp(Long timestamp) { + public Builder timestamp(Instant timestamp) { if (timestamp != null) this.timestamp = timestamp; return this; } @@ -194,7 +198,7 @@ public class MetricsPacket { return ! metrics.isEmpty(); } - public Instant getTimestamp() { return Instant.ofEpochSecond(timestamp); } + public Instant getTimestamp() { return timestamp; } } diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java index 3d2bf7aaecf..cabcde7cbb4 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonUtil.java @@ -50,7 +50,7 @@ public class GenericJsonUtil { public static GenericJsonModel toGenericJsonModel(List<MetricsPacket> metricsPackets, Node node) { Map<ServiceId, List<MetricsPacket>> packetsByService = metricsPackets.stream() - .collect(Collectors.groupingBy(packet -> packet.service, LinkedHashMap::new, toList())); + .collect(Collectors.groupingBy(MetricsPacket::service, LinkedHashMap::new, toList())); var jsonModel = new GenericJsonModel(); if (node != null) { @@ -66,13 +66,13 @@ public class GenericJsonUtil { .toList(); var genericService = packets.stream().findFirst() .map(firstPacket -> new GenericService(serviceId.id, - firstPacket.timestamp, - StatusCode.values()[firstPacket.statusCode], - firstPacket.statusMessage, + firstPacket.timestamp(), + StatusCode.values()[firstPacket.statusCode()], + firstPacket.statusMessage(), genericMetricsList)) .get(); if (VESPA_NODE_SERVICE_ID.equals(serviceId)) { - jsonModel.node = new GenericNode(genericService.timestamp, genericService.metrics); + jsonModel.node = new GenericNode(genericService.timeAsInstant(), genericService.metrics); } else { genericServices.add(genericService); @@ -107,13 +107,13 @@ public class GenericJsonUtil { if (node.metrics == null || node.metrics.isEmpty()) { return List.of(new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID) .statusCode(StatusCode.UP.ordinal()) - .timestamp(node.timestamp)); + .timestamp(node.timeAsInstant())); } for (var genericMetrics : node.metrics) { var packet = new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID) .statusCode(StatusCode.UP.ordinal()) - .timestamp(node.timestamp); + .timestamp(node.timeAsInstant()); addMetrics(genericMetrics, packet); packets.add(packet); } @@ -138,7 +138,7 @@ public class GenericJsonUtil { return new MetricsPacket.Builder(ServiceId.toServiceId(service.name)) .statusCode(StatusCode.fromString(service.status.code).ordinal()) .statusMessage(service.status.description) - .timestamp(service.timestamp); + .timestamp(service.timeAsInstant()); } private static void addMetrics(GenericMetrics genericMetrics, MetricsPacket.Builder packet) { diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericNode.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericNode.java index d0a0b04b629..6c319ee0223 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericNode.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericNode.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import java.time.Instant; import java.util.List; import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT; @@ -19,15 +20,18 @@ import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT; public class GenericNode { @JsonProperty("timestamp") - public Long timestamp; + public Long timestamp = Instant.EPOCH.getEpochSecond(); @JsonProperty("metrics") public List<GenericMetrics> metrics; - public GenericNode() { } + public GenericNode() {} - GenericNode(Long timestamp, List<GenericMetrics> metrics) { - this.timestamp = timestamp; + GenericNode(Instant timestamp, List<GenericMetrics> metrics) { + this.timestamp = timestamp.getEpochSecond(); this.metrics = metrics; } + public Instant timeAsInstant() { + return Instant.ofEpochSecond(timestamp); + } } diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericService.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericService.java index 7e20be22793..b4fdd17c681 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericService.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/GenericService.java @@ -6,7 +6,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.ser.BeanPropertyWriter; +import java.time.Instant; import java.util.List; import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_ABSENT; @@ -35,13 +37,17 @@ public class GenericService { public GenericService() { } // TODO: take StatusCode instead of int - GenericService(String name, Long timestamp, StatusCode statusCode, String message, List<GenericMetrics> metrics) { + GenericService(String name, Instant timestamp, StatusCode statusCode, String message, List<GenericMetrics> metrics) { this.name = name; - this.timestamp = timestamp; + this.timestamp = timestamp.getEpochSecond(); status = new Status(statusCode, message); this.metrics = metrics; } + public Instant timeAsInstant() { + return Instant.ofEpochSecond(timestamp); + } + @JsonInclude(NON_EMPTY) @JsonPropertyOrder({ "code", "description" }) diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java index 649a4978ed9..dbd35bf8868 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtil.java @@ -13,6 +13,7 @@ import com.fasterxml.jackson.core.util.MinimalPrettyPrinter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -42,7 +43,7 @@ public class YamasJsonUtil { return new MetricsPacket.Builder(ServiceId.toServiceId(jsonModel.application)) .statusCode(jsonModel.status_code) .statusMessage(jsonModel.status_msg) - .timestamp(jsonModel.timestamp) + .timestamp(Instant.ofEpochSecond(jsonModel.timestamp)) .putMetrics(jsonModel.getMetricsList()) .putDimensions(jsonModel.getDimensionsById()) .addConsumers(jsonModel.getYamasConsumers()); @@ -124,12 +125,12 @@ public class YamasJsonUtil { private static void toJson(MetricsPacket metric, JsonGenerator generator, boolean addStatus) throws IOException { generator.writeStartObject(); if (addStatus) { - generator.writeNumberField("status_code", metric.statusCode); + generator.writeNumberField("status_code", metric.statusCode()); } - if (metric.timestamp != 0) { - generator.writeNumberField("timestamp", metric.timestamp); + if ( ! Instant.EPOCH.equals(metric.timestamp())) { + generator.writeNumberField("timestamp", metric.timestamp().getEpochSecond()); } - generator.writeStringField("application", metric.service.id); + generator.writeStringField("application", metric.service().id); if ( ! metric.metrics().isEmpty()) { generator.writeObjectFieldStart("metrics"); @@ -160,7 +161,7 @@ public class YamasJsonUtil { generator.writeEndObject(); } if (addStatus) { - generator.writeStringField("status_msg", metric.statusMessage); + generator.writeStringField("status_msg", metric.statusMessage()); } generator.writeEndObject(); } diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/prometheus/PrometheusModel.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/prometheus/PrometheusModel.java index 1f55e2f8679..b4d26069b6f 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/prometheus/PrometheusModel.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/prometheus/PrometheusModel.java @@ -64,7 +64,7 @@ public class PrometheusModel implements Enumeration<MetricFamilySamples> { for (var packet : packets) { Number metric = packet.metrics().get(metricId); if (metric != null) { - sampleList.add(createSample(serviceId, metricId, metric, packet.timestamp, packet.dimensions())); + sampleList.add(createSample(serviceId, metricId, metric, packet.timestamp().toEpochMilli(), packet.dimensions())); } } })); diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/prometheus/PrometheusUtil.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/prometheus/PrometheusUtil.java index 47b97fa0902..d909944fe4d 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/prometheus/PrometheusUtil.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/metric/model/prometheus/PrometheusUtil.java @@ -32,7 +32,7 @@ public class PrometheusUtil { } Map<ServiceId, List<MetricsPacket>> packetsByService = metricsPackets.stream() - .collect(Collectors.groupingBy(packet -> packet.service)); + .collect(Collectors.groupingBy(MetricsPacket::service)); List<MetricFamilySamples> statusMetrics = new ArrayList<>(packetsByService.size()); packetsByService.forEach(((serviceId, packets) -> { @@ -41,9 +41,9 @@ public class PrometheusUtil { var firstPacket = packets.get(0); var statusMetricName = serviceName + "_status"; // MetricsPacket status 0 means OK, but it's the opposite in Prometheus. - var statusMetricValue = (firstPacket.statusCode == 0) ? 1 : 0; + var statusMetricValue = (firstPacket.statusCode() == 0) ? 1 : 0; var sampleList = List.of(new Collector.MetricFamilySamples.Sample(statusMetricName, List.of(), List.of(), - statusMetricValue, firstPacket.timestamp * 1000)); + statusMetricValue, firstPacket.timestamp().toEpochMilli())); statusMetrics.add(new Collector.MetricFamilySamples(statusMetricName, Collector.Type.UNKNOWN, "status of service", sampleList)); } })); diff --git a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/node/NodeMetricGatherer.java b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/node/NodeMetricGatherer.java index ded2af0542f..b6c78197cda 100644 --- a/metrics-proxy/src/main/java/ai/vespa/metricsproxy/node/NodeMetricGatherer.java +++ b/metrics-proxy/src/main/java/ai/vespa/metricsproxy/node/NodeMetricGatherer.java @@ -15,6 +15,7 @@ import com.yahoo.component.annotation.Inject; import com.yahoo.container.jdisc.state.FileWrapper; import com.yahoo.container.jdisc.state.HostLifeGatherer; +import java.time.Instant; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -56,7 +57,7 @@ public class NodeMetricGatherer { protected static void addObjectToBuilders(List<MetricsPacket.Builder> builders, JsonNode object) { MetricsPacket.Builder builder = new MetricsPacket.Builder(ServiceId.toServiceId(object.get("application").textValue())); - builder.timestamp(object.get("timestamp").longValue()); + builder.timestamp(Instant.ofEpochSecond(object.get("timestamp").longValue())); if (object.has("metrics")) { JsonNode metrics = object.get("metrics"); Iterator<?> keys = metrics.fieldNames(); diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/core/MetricsManagerTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/core/MetricsManagerTest.java index c63e0d7a0f0..64c5f75dd2e 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/core/MetricsManagerTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/core/MetricsManagerTest.java @@ -165,7 +165,7 @@ public class MetricsManagerTest { List<MetricsPacket> packets = metricsManager.getMetrics(testServices, Instant.EPOCH); MetricsPacket extraPacket = null; for (MetricsPacket packet : packets) { - if (packet.service.equals(serviceId)) extraPacket = packet; + if (packet.service().equals(serviceId)) extraPacket = packet; } assertNotNull(extraPacket); } @@ -226,7 +226,7 @@ public class MetricsManagerTest { private Instant getAdjustedTimestamp(Instant startTime, Instant metricTime) { MetricsPacket.Builder builder = new MetricsPacket.Builder(toServiceId("foo")) - .timestamp(metricTime.getEpochSecond()); + .timestamp(metricTime); return MetricsManager.adjustTimestamp(builder, startTime).getTimestamp(); } diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/HttpHandlerTestBase.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/HttpHandlerTestBase.java index dbc0605d0a9..8ebcabe993d 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/HttpHandlerTestBase.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/HttpHandlerTestBase.java @@ -55,7 +55,7 @@ public class HttpHandlerTestBase { MetricsManager metricsManager = TestUtil.createMetricsManager(vespaServices, getMetricsConsumers(), getApplicationDimensions(), getNodeDimensions()); metricsManager.setExtraMetrics(List.of( new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID) - .timestamp(Instant.now().getEpochSecond()) + .timestamp(Instant.now()) .putMetrics(List.of(new Metric(MetricId.toMetricId(CPU_METRIC), 12.345))))); return metricsManager; } diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/metrics/MetricsHandlerTestBase.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/metrics/MetricsHandlerTestBase.java index 8e80dbddf9e..70cc8d1ab78 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/metrics/MetricsHandlerTestBase.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/metrics/MetricsHandlerTestBase.java @@ -12,6 +12,7 @@ import org.junit.Ignore; import org.junit.Test; import java.io.IOException; +import java.time.Instant; import java.util.Locale; import static ai.vespa.metricsproxy.metric.dimensions.PublicDimensions.INTERNAL_SERVICE_ID; @@ -172,10 +173,10 @@ public abstract class MetricsHandlerTestBase<MODEL> extends HttpHandlerTestBase public void all_timestamps_are_equal_and_non_zero() { GenericJsonModel jsonModel = getResponseAsGenericJsonModel(DEFAULT_CONSUMER); - Long nodeTimestamp = jsonModel.node.timestamp; - assertNotEquals(0L, (long) nodeTimestamp); + Instant nodeTimestamp = jsonModel.node.timeAsInstant(); + assertNotEquals(Instant.EPOCH, nodeTimestamp); for (var service : jsonModel.services) - assertEquals(nodeTimestamp, service.timestamp); + assertEquals(nodeTimestamp, service.timeAsInstant()); } @Test diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/prometheus/PrometheusHandlerTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/prometheus/PrometheusHandlerTest.java index fafdb5a2d0c..a1145577db9 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/prometheus/PrometheusHandlerTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/http/prometheus/PrometheusHandlerTest.java @@ -2,6 +2,8 @@ package ai.vespa.metricsproxy.http.prometheus; import ai.vespa.metricsproxy.http.HttpHandlerTestBase; +import ai.vespa.metricsproxy.metric.model.MetricsPacket; +import ai.vespa.metricsproxy.metric.model.prometheus.PrometheusUtil; import ai.vespa.metricsproxy.service.DummyService; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; @@ -10,9 +12,14 @@ import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; +import java.time.Instant; +import java.util.List; import java.util.concurrent.Executors; import static ai.vespa.metricsproxy.metric.dimensions.PublicDimensions.REASON; +import static ai.vespa.metricsproxy.metric.model.DimensionId.toDimensionId; +import static ai.vespa.metricsproxy.metric.model.MetricId.toMetricId; +import static ai.vespa.metricsproxy.metric.model.ServiceId.toServiceId; import static ai.vespa.metricsproxy.metric.model.json.JacksonUtil.objectMapper; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -97,4 +104,21 @@ public class PrometheusHandlerTest extends HttpHandlerTestBase { } throw new IllegalArgumentException("No line containing string: " + searchString); } + + @Test + public void timestamp_is_in_milliseconds() { + Instant packetTimestamp = Instant.ofEpochMilli(123456789L); + var servicePacket = new MetricsPacket.Builder(toServiceId("my-service")) + .timestamp(packetTimestamp) + .statusCode(0) + .putMetric(toMetricId("service-metric"), 1234) + .putDimension(toDimensionId("service-dim"), "service-dim-value") + .build(); + var model = PrometheusUtil.toPrometheusModel(List.of(servicePacket)); + assertTrue(model.hasMoreElements()); + var metricsFamily = model.nextElement(); + assertEquals(1, metricsFamily.samples.size()); + var sample = metricsFamily.samples.get(0); + assertEquals(Instant.ofEpochMilli(sample.timestampMs), packetTimestamp); + } } diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/ExternalMetricsTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/ExternalMetricsTest.java index bfe70ceb780..14c23bcba87 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/ExternalMetricsTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/ExternalMetricsTest.java @@ -46,7 +46,7 @@ public class ExternalMetricsTest { List<MetricsPacket.Builder> packets = externalMetrics.getMetrics(); assertEquals(1, packets.size()); - assertEquals(SERVICE_ID, packets.get(0).build().service); + assertEquals(SERVICE_ID, packets.get(0).build().service()); } @Test diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/MetricsPacketTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/MetricsPacketTest.java index 7b490814f60..55d19e06c1d 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/MetricsPacketTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/MetricsPacketTest.java @@ -4,6 +4,7 @@ package ai.vespa.metricsproxy.metric.model; import ai.vespa.metricsproxy.metric.Metric; import org.junit.Test; +import java.time.Instant; import java.util.List; import java.util.Map; import java.util.Set; @@ -27,7 +28,7 @@ public class MetricsPacketTest { MetricsPacket packet = new MetricsPacket.Builder(null) .statusCode(0) .statusMessage("") - .timestamp(0L) + .timestamp(Instant.EPOCH) .build(); fail("Expected exception due to null service."); } catch (Exception e) { diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericApplicationModelTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericApplicationModelTest.java index 54736851b3f..2cd024a6147 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericApplicationModelTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericApplicationModelTest.java @@ -7,6 +7,7 @@ import ai.vespa.metricsproxy.metric.model.StatusCode; import org.junit.Test; import java.io.IOException; +import java.time.Instant; import java.util.List; import java.util.Map; @@ -51,13 +52,13 @@ public class GenericApplicationModelTest { @Test public void metrics_packets_can_be_converted_to_generic_json_model() throws Exception { var nodePacket = new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID) - .timestamp(123456L) + .timestamp(Instant.ofEpochSecond(123456L)) .putMetric(toMetricId("node-metric"), 1.234) .putDimension(toDimensionId("node-dim"), "node-dim-value") .build(); var servicePacket = new MetricsPacket.Builder(toServiceId("my-service")) - .timestamp(123456L) + .timestamp(Instant.ofEpochSecond(123456L)) .statusCode(0) .putMetric(toMetricId("service-metric"), 1234) .putDimension(toDimensionId("service-dim"), "service-dim-value") @@ -94,7 +95,7 @@ public class GenericApplicationModelTest { private MetricsPacket createMetricsPacket(String service, Number metricsValue, boolean isNode) { return new MetricsPacket.Builder(isNode ? VESPA_NODE_SERVICE_ID : toServiceId(service)) - .timestamp(1234L) + .timestamp(Instant.ofEpochSecond(1234L)) .statusCode(0) .putMetric(toMetricId(service + "-metric"), metricsValue) .putDimension(toDimensionId(service + "-dim"), isNode ? "node-dim-value" : "service-dim-value") diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java index 9eb1ed8cd5a..40ffbba84f0 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/GenericJsonModelTest.java @@ -6,6 +6,7 @@ import ai.vespa.metricsproxy.metric.model.StatusCode; import org.junit.Test; import java.io.IOException; +import java.time.Instant; import java.util.List; import static ai.vespa.metricsproxy.TestUtil.getFileContents; @@ -79,13 +80,13 @@ public class GenericJsonModelTest { @Test public void metrics_packets_can_be_converted_to_generic_json_model() throws Exception { var nodePacket = new MetricsPacket.Builder(VESPA_NODE_SERVICE_ID) - .timestamp(123456L) + .timestamp(Instant.ofEpochSecond(123456L)) .putMetric(toMetricId("node-metric"), 1.234) .putDimension(toDimensionId("node-dim"), "node-dim-value") .build(); var servicePacket = new MetricsPacket.Builder(toServiceId("my-service")) - .timestamp(123456L) + .timestamp(Instant.ofEpochSecond(123456L)) .statusCode(0) .putMetric(toMetricId("service-metric"), 1234) .putDimension(toDimensionId("service-dim"), "service-dim-value") diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java index 8f3a99c1c68..f55f3219896 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonModelTest.java @@ -65,7 +65,7 @@ public class YamasJsonModelTest { MetricsPacket metricsPacket = YamasJsonUtil.toMetricsPacketBuilder(jsonModel).build(); // Do some sanity checking - assertEquals(toServiceId("vespa.searchnode"), metricsPacket.service); + assertEquals(toServiceId("vespa.searchnode"), metricsPacket.service()); assertTrue(metricsPacket.consumers().contains(toConsumerId("Vespa"))); assertEquals(5.555555555E9, metricsPacket.metrics().get(toMetricId("memory_rss")).doubleValue(), 0.1d); //Not using custom double rendrer diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtilTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtilTest.java index aa85277b3b7..7f82092e9e4 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtilTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/metric/model/json/YamasJsonUtilTest.java @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import org.junit.Test; import java.io.IOException; +import java.time.Instant; import java.util.List; import java.util.Set; @@ -43,7 +44,7 @@ public class YamasJsonUtilTest { @Test public void timestamp_0_in_packet_is_translated_to_null_in_json_model() throws IOException { - MetricsPacket packet = new MetricsPacket.Builder(toServiceId("foo")).timestamp(0L).build(); + MetricsPacket packet = new MetricsPacket.Builder(toServiceId("foo")).timestamp(Instant.EPOCH).build(); JsonNode json = metrics(packet, true); assertFalse(json.has("timestamp")); } diff --git a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/node/NodeMetricGathererTest.java b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/node/NodeMetricGathererTest.java index 20164b91a55..32123068968 100644 --- a/metrics-proxy/src/test/java/ai/vespa/metricsproxy/node/NodeMetricGathererTest.java +++ b/metrics-proxy/src/test/java/ai/vespa/metricsproxy/node/NodeMetricGathererTest.java @@ -27,8 +27,8 @@ public class NodeMetricGathererTest { NodeMetricGatherer.addObjectToBuilders(builders, hostLifePacket); MetricsPacket packet = builders.remove(0).build(); - assertEquals("host_life", packet.service.id); - assertEquals(123, packet.timestamp); + assertEquals("host_life", packet.service().id); + assertEquals(123, packet.timestamp().getEpochSecond()); assertEquals(12L, packet.metrics().get(MetricId.toMetricId("uptime"))); assertEquals(1L, packet.metrics().get(MetricId.toMetricId("alive"))); assertEquals(Set.of(ConsumerId.toConsumerId("Vespa")), packet.consumers()); diff --git a/model-integration/src/main/resources/configdefinitions/llm-local-client.def b/model-integration/src/main/resources/configdefinitions/llm-local-client.def index c06c24b33e5..4823a53ec46 100755 --- a/model-integration/src/main/resources/configdefinitions/llm-local-client.def +++ b/model-integration/src/main/resources/configdefinitions/llm-local-client.def @@ -5,13 +5,13 @@ package=ai.vespa.llm.clients model model # Maximum number of requests to handle in parallel pr container node -parallelRequests int default=10 +parallelRequests int default=1 # Additional number of requests to put in queue for processing before starting to reject new requests maxQueueSize int default=10 # Use GPU -useGpu bool default=false +useGpu bool default=true # Maximum number of model layers to run on GPU gpuLayers int default=1000000 @@ -22,7 +22,7 @@ threads int default=-1 # Context size for the model # Context is divided between parallel requests. So for 10 parallel requests, each "slot" gets 1/10 of the context -contextSize int default=512 +contextSize int default=4096 # Maximum number of tokens to process in one request - overriden by inference parameters maxTokens int default=512 diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java index a0f9d6e260a..74907feee41 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java @@ -29,7 +29,7 @@ public class ClusterModel { /** If we have less than this query rate, we cannot be fully confident in our load data, which influences some decisions. */ public static final double queryRateGivingFullConfidence = 100.0; - static final double idealQueryCpuLoad = 0.8; + static final double idealQueryCpuLoad = 0.75; static final double idealWriteCpuLoad = 0.95; static final double idealContainerMemoryLoad = 0.8; diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/filter/ParentHostFilter.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/filter/ParentHostFilter.java index d5aa82a8dc2..821fcd51e18 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/filter/ParentHostFilter.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/filter/ParentHostFilter.java @@ -12,7 +12,7 @@ import java.util.stream.Collectors; /** * Filter based on the parent host value (for virtualized nodes). * - * @author dybis + * @author Haakon Dybdahl */ public class ParentHostFilter { diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java index ec48e1d5f34..46dfb51a433 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java @@ -49,15 +49,13 @@ public class CapacityPolicies { } private ClusterResources applyOn(ClusterResources resources, Capacity capacity, ApplicationId application, boolean exclusive) { - int nodes = decideSize(resources.nodes(), capacity.isRequired(), application.instance().isTester()); - int groups = Math.min(resources.groups(), nodes); // cannot have more groups than nodes - while (groups > 1 && nodes % groups != 0) - groups--; // Must be divisible by the number of groups + int nodes = decideCount(resources.nodes(), capacity.isRequired(), application.instance().isTester()); + int groups = decideGroups(resources.nodes(), resources.groups(), nodes); var nodeResources = decideNodeResources(resources.nodeResources(), capacity.isRequired(), exclusive); return new ClusterResources(nodes, groups, nodeResources); } - private int decideSize(int requested, boolean required, boolean isTester) { + private int decideCount(int requested, boolean required, boolean isTester) { if (isTester) return 1; if (required) return requested; @@ -69,6 +67,14 @@ public class CapacityPolicies { }; } + private int decideGroups(int requestedNodes, int requestedGroups, int decidedNodes) { + if (requestedNodes == decidedNodes) return requestedGroups; + int groups = Math.min(requestedGroups, decidedNodes); // cannot have more groups than nodes + while (groups > 1 && decidedNodes % groups != 0) + groups--; // Must be divisible by the number of groups + return groups; + } + private NodeResources decideNodeResources(NodeResources target, boolean required, boolean exclusive) { if (required || exclusive) return target; // Cannot downsize if resources are required, or exclusively allocated if (target.isUnspecified()) return target; // Cannot be modified diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java index d8565b81e41..fa0421555d4 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidate.java @@ -54,10 +54,6 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat /** True if this node is allocated on an exclusive network switch in its cluster */ final boolean exclusiveSwitch; - /** True if this node belongs to a group which will not be needed after this deployment */ - // TODO: Always false - final boolean isSurplus; - /** This node does not exist in the node repository yet */ final boolean isNew; @@ -68,7 +64,7 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat final boolean exclusiveParent; private NodeCandidate(NodeResources freeParentCapacity, Optional<Node> parent, boolean violatesSpares, boolean exclusiveSwitch, - boolean exclusiveParent, boolean isSurplus, boolean isNew, boolean isResizeable) { + boolean exclusiveParent, boolean isNew, boolean isResizeable) { if (isResizeable && isNew) throw new IllegalArgumentException("A new node cannot be resizable"); @@ -77,7 +73,6 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat this.violatesSpares = violatesSpares; this.exclusiveSwitch = exclusiveSwitch; this.exclusiveParent = exclusiveParent; - this.isSurplus = isSurplus; this.isNew = isNew; this.isResizable = isResizeable; } @@ -147,10 +142,6 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat if (this.state() == Node.State.active && other.state() != Node.State.active) return -1; if (other.state() == Node.State.active && this.state() != Node.State.active) return 1; - // Choose active node that is not retired first (surplus is active but retired) - if (!this.isSurplus && other.isSurplus) return -1; - if (!other.isSurplus && this.isSurplus) return 1; - // Choose reserved nodes from a previous allocation attempt (which exist in node repo) if (this.isInNodeRepoAndReserved() && ! other.isInNodeRepoAndReserved()) return -1; if (other.isInNodeRepoAndReserved() && ! this.isInNodeRepoAndReserved()) return 1; @@ -236,7 +227,7 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat /** Returns a copy of this with node set to given value */ NodeCandidate withNode(Node node, boolean retiredNow) { - return new ConcreteNodeCandidate(node, retiredNow, freeParentCapacity, parent, violatesSpares, exclusiveSwitch, exclusiveParent, isSurplus, isNew, isResizable); + return new ConcreteNodeCandidate(node, retiredNow, freeParentCapacity, parent, violatesSpares, exclusiveSwitch, exclusiveParent, isNew, isResizable); } /** Returns the switch priority, based on switch exclusivity, of this compared to other */ @@ -276,10 +267,9 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat NodeResources freeParentCapacity, Node parent, boolean violatesSpares, - boolean isSurplus, boolean isNew, boolean isResizeable) { - return new ConcreteNodeCandidate(node, false, freeParentCapacity, Optional.of(parent), violatesSpares, true, false, isSurplus, isNew, isResizeable); + return new ConcreteNodeCandidate(node, false, freeParentCapacity, Optional.of(parent), violatesSpares, true, false, isNew, isResizeable); } public static NodeCandidate createNewChild(NodeResources resources, @@ -292,11 +282,11 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat } public static NodeCandidate createNewExclusiveChild(Node node, Node parent) { - return new ConcreteNodeCandidate(node, false, node.resources(), Optional.of(parent), false, true, false, false, true, false); + return new ConcreteNodeCandidate(node, false, node.resources(), Optional.of(parent), false, true, false, true, false); } - public static NodeCandidate createStandalone(Node node, boolean isSurplus, boolean isNew) { - return new ConcreteNodeCandidate(node, false, node.resources(), Optional.empty(), false, true, false, isSurplus, isNew, false); + public static NodeCandidate createStandalone(Node node, boolean isNew) { + return new ConcreteNodeCandidate(node, false, node.resources(), Optional.empty(), false, true, false, isNew, false); } /** A candidate backed by a node */ @@ -309,8 +299,8 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat boolean retiredNow, NodeResources freeParentCapacity, Optional<Node> parent, boolean violatesSpares, boolean exclusiveSwitch, boolean exclusiveParent, - boolean isSurplus, boolean isNew, boolean isResizeable) { - super(freeParentCapacity, parent, violatesSpares, exclusiveSwitch, exclusiveParent, isSurplus, isNew, isResizeable); + boolean isNew, boolean isResizeable) { + super(freeParentCapacity, parent, violatesSpares, exclusiveSwitch, exclusiveParent, isNew, isResizeable); this.retiredNow = retiredNow; this.node = Objects.requireNonNull(node, "Node cannot be null"); } @@ -348,7 +338,7 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat @Override public NodeCandidate allocate(ApplicationId owner, ClusterMembership membership, NodeResources requestedResources, Instant at) { return new ConcreteNodeCandidate(node.allocate(owner, membership, requestedResources, at), retiredNow, - freeParentCapacity, parent, violatesSpares, exclusiveSwitch, exclusiveParent, isSurplus, isNew, isResizable); + freeParentCapacity, parent, violatesSpares, exclusiveSwitch, exclusiveParent, isNew, isResizable); } /** Called when the node described by this candidate must be created */ @@ -358,13 +348,13 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat @Override public NodeCandidate withExclusiveSwitch(boolean exclusiveSwitch) { return new ConcreteNodeCandidate(node, retiredNow, freeParentCapacity, parent, violatesSpares, exclusiveSwitch, - exclusiveParent, isSurplus, isNew, isResizable); + exclusiveParent, isNew, isResizable); } @Override public NodeCandidate withExclusiveParent(boolean exclusiveParent) { return new ConcreteNodeCandidate(node, retiredNow, freeParentCapacity, parent, violatesSpares, exclusiveSwitch, - exclusiveParent, isSurplus, isNew, isResizable); + exclusiveParent, isNew, isResizable); } @Override @@ -408,7 +398,7 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat boolean exclusiveParent, LockedNodeList allNodes, IP.Allocation.Context ipAllocationContext) { - super(freeParentCapacity, Optional.of(parent), violatesSpares, exclusiveSwitch, exclusiveParent, false, true, false); + super(freeParentCapacity, Optional.of(parent), violatesSpares, exclusiveSwitch, exclusiveParent, true, false); this.resources = resources; this.allNodes = allNodes; this.ipAllocationContext = ipAllocationContext; @@ -468,7 +458,7 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat NodeType.tenant) .cloudAccount(parent.get().cloudAccount()) .build(); - return new ConcreteNodeCandidate(node, false, freeParentCapacity, parent, violatesSpares, exclusiveSwitch, exclusiveParent, isSurplus, isNew, isResizable); + return new ConcreteNodeCandidate(node, false, freeParentCapacity, parent, violatesSpares, exclusiveSwitch, exclusiveParent, isNew, isResizable); } @@ -516,7 +506,7 @@ public abstract class NodeCandidate implements Nodelike, Comparable<NodeCandidat private InvalidNodeCandidate(NodeResources resources, NodeResources freeParentCapacity, Node parent, String invalidReason) { - super(freeParentCapacity, Optional.of(parent), false, false, false, false, true, false); + super(freeParentCapacity, Optional.of(parent), false, false, false, true, false); this.resources = resources; this.invalidReason = invalidReason; } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java index 3ff970e5645..65dc6a0c7d0 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodePrioritizer.java @@ -157,7 +157,7 @@ public class NodePrioritizer { .filter(node -> node.allocation().get().owner().equals(application)) .filter(node -> node.allocation().get().membership().cluster().id().equals(clusterSpec.id())) .filter(node -> node.state() == Node.State.active || canStillAllocate(node)) - .map(node -> candidateFrom(node, false)) + .map(node -> candidateFrom(node)) .forEach(candidates::add); } @@ -166,13 +166,13 @@ public class NodePrioritizer { allNodes.stream() .filter(node -> node.type() == requested.type()) .filter(node -> node.state() == Node.State.ready) - .map(node -> candidateFrom(node, false)) + .map(node -> candidateFrom(node)) .filter(n -> !n.violatesSpares || canAllocateToSpareHosts) .forEach(candidates::add); } /** Create a candidate from given pre-existing node */ - private NodeCandidate candidateFrom(Node node, boolean isSurplus) { + private NodeCandidate candidateFrom(Node node) { Optional<Node> optionalParent = allNodes.parentOf(node); if (optionalParent.isPresent()) { Node parent = optionalParent.get(); @@ -180,7 +180,6 @@ public class NodePrioritizer { capacity.availableCapacityOf(parent), parent, spareHosts.contains(parent), - isSurplus, false, parent.exclusiveToApplicationId().isEmpty() && requested.canResize(node.resources(), @@ -189,7 +188,7 @@ public class NodePrioritizer { topologyChange, currentClusterSize)); } else { - return NodeCandidate.createStandalone(node, isSurplus, false); + return NodeCandidate.createStandalone(node, false); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ContainerConfig.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ContainerConfig.java index 81a490939d6..5795e25d247 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ContainerConfig.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/ContainerConfig.java @@ -8,7 +8,7 @@ import com.yahoo.config.provision.SystemName; * For running NodeRepository API with some mocked data. * This is used by both NodeAdmin and NodeRepository tests. * - * @author dybis + * @author Haakon Dybdahl */ public class ContainerConfig { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java index 830ff170a90..8374c41ea25 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java @@ -85,7 +85,7 @@ public class AutoscalingTest { fixture.loader().applyCpuLoad(0.7f, 10); var scaledResources = fixture.tester().assertResources("Scaling up since resource usage is too high", - 9, 1, 2.8, 6.8, 288.7, + 9, 1, 3.0, 6.8, 288.7, fixture.autoscale()); fixture.deploy(Capacity.from(scaledResources)); @@ -131,7 +131,7 @@ public class AutoscalingTest { fixture.loader().applyLoad(new Load(0.1, 0.1, 0.1, 0, 0), 3); fixture.loader().applyLoad(new Load(1.0, 1.0, 1.0, 0, 0), 1); fixture.tester().assertResources("Scaling up since resource usage is too high", - 8, 1, 5.3, 17.0, 75.1, + 8, 1, 5.7, 17.0, 75.1, fixture.autoscale()); } @@ -192,7 +192,7 @@ public class AutoscalingTest { fixture.setScalingDuration(Duration.ofHours(12)); // Fixture sets last completion to be 1 day into the past fixture.loader().applyLoad(new Load(1.0, 0.1, 1.0, 0, 0), 10); fixture.tester().assertResources("Scaling up (only) since resource usage is too high", - 5, 1, 11.7, 14.9, 131.5, + 5, 1, 12.5, 14.9, 131.5, fixture.autoscale()); } @@ -204,7 +204,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(Duration.ofDays(2)); fixture.loader().applyLoad(new Load(1.0, 0.1, 1.0, 0, 0), 10); fixture.tester().assertResources("Scaling cpu and disk up and memory down", - 5, 1, 11.7, 4.0, 131.5, + 5, 1, 12.5, 4.0, 131.5, fixture.autoscale()); } @@ -215,7 +215,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(Duration.ofDays(2)); fixture.loader().applyLoad(new Load(1.0, 0.1, 1.0, 0, 0), 10); fixture.tester().assertResources("Scaling cpu and disk up, memory follows", - 16, 1, 4, 8.0, 28.3, + 8, 1, 8, 16.0, 60.7, fixture.autoscale()); } @@ -227,7 +227,7 @@ public class AutoscalingTest { fixture.loader().applyCpuLoad(0.70, 1); fixture.loader().applyCpuLoad(0.01, 100); fixture.tester().assertResources("Scaling up since peak resource usage is too high", - 5, 1, 7.1, 11.9, 50.5, + 5, 1, 7.6, 11.9, 50.5, fixture.autoscale()); } @@ -239,7 +239,7 @@ public class AutoscalingTest { fixture.loader().applyCpuLoad(0.70, 1); fixture.loader().applyCpuLoad(0.01, 100); fixture.tester().assertResources("Scaling up since peak resource usage is too high", - 9, 1, 4, 8.0, 100, + 5, 1, 8, 16.0, 200, fixture.autoscale()); } @@ -251,7 +251,7 @@ public class AutoscalingTest { fixture.loader().applyCpuLoad(0.70, 1); fixture.loader().applyCpuLoad(0.01, 100); fixture.tester().assertResources("Scaling up cpu since peak resource usage is too high", - 5, 1, 7.1, 12.8, 60.0, + 5, 1, 7.6, 12.8, 60.0, fixture.autoscale()); } @@ -279,14 +279,14 @@ public class AutoscalingTest { fixture.loader().applyCpuLoad(0.25f, 120); var scaledResources = fixture.tester().assertResources("Scaling cpu up", - 3, 1, 4, 16.0, 40.8, + 6, 1, 2, 16.0, 40.8, fixture.autoscale()); fixture.deploy(Capacity.from(scaledResources)); fixture.deactivateRetired(Capacity.from(scaledResources)); fixture.completeLastScaling(); fixture.loader().applyCpuLoad(0.1f, 120); fixture.tester().assertResources("Scaling down since cpu usage has gone down", - 3, 1, 2, 16, 75.0, + 4, 1, 2, 16, 34.0, fixture.autoscale()); } @@ -314,7 +314,7 @@ public class AutoscalingTest { new NodeResources(100, 1000, 1000, 1, DiskSpeed.any)); var capacity = Capacity.from(min, max); ClusterResources scaledResources = fixture.tester().assertResources("Scaling up", - 13, 1, 1.5, 29.1, 87.3, + 14, 1, 1.5, 27.2, 81.5, fixture.autoscale(capacity)); assertEquals("Disk speed from new capacity is used", DiskSpeed.any, scaledResources.nodeResources().diskSpeed()); @@ -415,7 +415,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(0.5, 240); fixture.tester().assertResources("Scaling cpu up", - 6, 6, 4.5, 7.4, 22.3, + 6, 6, 4.8, 7.4, 22.3, fixture.autoscale()); } @@ -432,7 +432,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(0.6, 240); fixture.tester().assertResources("Scaling cpu up", - 12, 6, 3.0, 4.2, 27.5, + 12, 6, 3.2, 4.2, 27.5, fixture.autoscale()); } @@ -478,7 +478,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(1.0, 120); fixture.tester().assertResources("Suggesting above capacity limit", - 5, 1, 10.2, 11.9, 50.5, + 5, 1, 10.9, 11.9, 50.5, fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min)); } @@ -490,7 +490,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(1.0, 120); fixture.tester().assertResources("Suggesting above capacity limit", - 13, 1, 4, 8, 100.0, + 7, 1, 8, 16, 200.0, fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min)); } @@ -538,7 +538,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyLoad(new Load(0.5, 0.8, 0.1, 0, 0), 120); fixture.tester().assertResources("Suggesting resources where disk is 3x memory (this is a content cluster)", - 11, 1, 13.0, 60.0, 179.9, + 11, 1, 13.9, 60.0, 179.9, fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min)); fixture.tester().assertResources("Autoscaling to resources where disk is 3x memory (this is a content cluster)", 10, 1, 10.0, 66.2, 198.6, @@ -559,7 +559,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyLoad(new Load(0.5, 0.8, 0.1, 0, 0), 120); fixture.tester().assertResources("Suggesting resources where disk is 3x memory (this is a content cluster)", - 13, 1, 36.0, 72.0, 900.0, + 7, 1, 72.0, 144.0, 1800.0, fixture.tester().suggest(fixture.applicationId, fixture.clusterSpec.id(), min, min)); fixture.tester().assertResources("Autoscaling to resources where disk is 3x memory (this is a content cluster)", 10, 1, 16.0, 64, 247.5, @@ -579,7 +579,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyCpuLoad(0.9, 120); fixture.tester().assertResources("Scaling up to 2 nodes, scaling memory and disk down at the same time", - 8, 4, 7.4, 41.5, 124.6, + 8, 4, 7.9, 41.5, 124.6, fixture.autoscale()); } @@ -597,7 +597,7 @@ public class AutoscalingTest { fixture.setScalingDuration(Duration.ofHours(6)); fixture.loader().applyCpuLoad(0.9, 120); fixture.tester().assertResources("Scaling up to 2 nodes, scaling memory and disk down at the same time", - 7, 7, 9.4, 78.6, 235.8, + 8, 8, 8.6, 78.6, 235.8, fixture.autoscale()); } @@ -616,7 +616,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(timePassed.negated()); fixture.loader().addLoadMeasurements(10, t -> t == 0 ? 200.0 : 100.0, t -> 10.0); fixture.tester().assertResources("Changing to 1 group is cheaper", - 7, 1, 2.5, 43.3, 129.8, + 7, 1, 2.7, 43.3, 129.8, fixture.autoscale()); } @@ -653,7 +653,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(1)); fixture.loader().applyMemLoad(1.0, 1000); fixture.tester().assertResources("Increase group size to reduce memory load", - 8, 2, 13.9, 96.3, 288.8, + 8, 2, 14.0, 96.3, 288.8, fixture.autoscale()); } @@ -670,7 +670,7 @@ public class AutoscalingTest { fixture.tester().clock().advance(Duration.ofDays(2)); fixture.loader().applyLoad(new Load(0.16, 0.02, 0.5, 0, 0), 120); fixture.tester().assertResources("Scaling down memory", - 6, 1, 2.1, 4.0, 96.2, + 6, 1, 2.3, 4.0, 96.2, fixture.autoscale()); } @@ -726,16 +726,16 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.25, 200); fixture.tester().assertResources("Scale up since we assume we need 2x cpu for growth when no scaling time data", - 5, 1, 2.6, 11.9, 50.5, + 5, 1, 2.7, 11.9, 50.5, fixture.autoscale()); fixture.setScalingDuration(Duration.ofHours(8)); fixture.tester().clock().advance(Duration.ofDays(2)); timeAdded = fixture.loader().addLoadMeasurements(100, t -> 100.0 + (t < 50 ? t : 100 - t), t -> 0.0); fixture.tester.clock().advance(timeAdded.negated()); - fixture.loader().addCpuMeasurements(0.20, 200); + fixture.loader().addCpuMeasurements(0.15, 200); fixture.tester().assertResources("Scale down since observed growth is slower than scaling time", - 5, 1, 1.6, 11.9, 50.5, + 5, 1, 1.3, 11.9, 50.5, fixture.autoscale()); fixture.setScalingDuration(Duration.ofHours(8)); @@ -746,7 +746,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.25, 200); fixture.tester().assertResources("Scale up since observed growth is faster than scaling time", - 5, 1, 2.4, 11.9, 50.5, + 5, 1, 2.6, 11.9, 50.5, fixture.autoscale()); } @@ -763,7 +763,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.7, 200); fixture.tester().assertResources("Scale up slightly since observed growth is faster than scaling time, but we are not confident", - 5, 1, 2.2, 11.9, 50.5, + 5, 1, 2.4, 11.9, 50.5, fixture.autoscale()); } @@ -782,7 +782,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.4, 200); fixture.tester.assertResources("Query and write load is equal -> scale up somewhat", - 5, 1, 2.9, 11.9, 50.5, + 5, 1, 3.1, 11.9, 50.5, fixture.autoscale()); fixture.tester().clock().advance(Duration.ofDays(2)); @@ -791,7 +791,7 @@ public class AutoscalingTest { fixture.loader().addCpuMeasurements(0.4, 200); // TODO: Ackhually, we scale up less here - why? fixture.tester().assertResources("Query load is 4x write load -> scale up more", - 5, 1, 2.2, 11.9, 50.5, + 5, 1, 2.4, 11.9, 50.5, fixture.autoscale()); fixture.tester().clock().advance(Duration.ofDays(2)); @@ -807,7 +807,7 @@ public class AutoscalingTest { fixture.tester.clock().advance(timeAdded.negated()); fixture.loader().addCpuMeasurements(0.4, 200); fixture.tester().assertResources("Query only -> larger", - 5, 1, 3.5, 11.9, 50.5, + 5, 1, 3.8, 11.9, 50.5, fixture.autoscale()); fixture.tester().clock().advance(Duration.ofDays(2)); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java index dfec423d77b..6c2a5565c4a 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingUsingBcpGroupInfoTest.java @@ -33,7 +33,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.1, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 3.4, 7.2, 28.8, + 8, 1, 3.6, 7.2, 28.8, fixture.autoscale()); // Higher query rate @@ -41,7 +41,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(200, 1.1, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 6.8, 7.2, 28.8, + 8, 1, 7.1, 7.2, 28.8, fixture.autoscale()); // Higher headroom @@ -49,7 +49,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.3, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 4.0, 7.2, 28.8, + 8, 1, 4.2, 7.2, 28.8, fixture.autoscale()); // Higher per query cost @@ -57,7 +57,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.1, 0.45)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 5.1, 7.2, 28.8, + 8, 1, 5.4, 7.2, 28.8, fixture.autoscale()); // Bcp elsewhere is 0 - use local only @@ -65,7 +65,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(0, 1.1, 0.45)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling using local info", - 8, 1, 1, 7.2, 28.8, + 8, 1, 1.1, 7.2, 28.8, fixture.autoscale()); } @@ -86,7 +86,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.1, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 3, 3, 11.7, 41.8, 189.3, + 3, 3, 12.3, 41.8, 189.3, fixture.autoscale()); // Higher query rate @@ -94,7 +94,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(200, 1.1, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 3, 3, 23.1, 41.8, 189.3, + 3, 3, 24.4, 41.8, 189.3, fixture.autoscale()); // Higher headroom @@ -102,7 +102,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.3, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 3, 3, 13.8, 41.8, 189.3, + 3, 3, 14.5, 41.8, 189.3, fixture.autoscale()); // Higher per query cost @@ -110,7 +110,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.1, 0.45)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 3, 3, 17.4, 41.8, 189.3, + 3, 3, 18.4, 41.8, 189.3, fixture.autoscale()); } @@ -128,7 +128,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.1, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 4, 1, 8.0, 16.0, 40.8, + 8, 1, 4.0, 16.0, 40.8, fixture.autoscale()); // Higher query rate (mem and disk changes are due to being assigned larger hosts where we get less overhead share @@ -136,7 +136,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(200, 1.1, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 7, 1, 8.0, 16.0, 40.8, + 8, 1, 8.0, 16.0, 40.8, fixture.autoscale()); // Higher headroom @@ -144,7 +144,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.3, 0.3)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 4.0, 16.0, 40.8, + 5, 1, 8.0, 16.0, 40.8, fixture.autoscale()); // Higher per query cost @@ -152,7 +152,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(100, 1.1, 0.45)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 10, 1, 4.0, 16.0, 40.8, + 6, 1, 8.0, 16.0, 40.8, fixture.autoscale()); } @@ -187,7 +187,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.store(new BcpGroupInfo(200, 1.3, 0.45)); fixture.loader().addCpuMeasurements(0.7f, 10); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 11.9, 7.2, 28.8, + 8, 1, 12.6, 7.2, 28.8, fixture.autoscale()); // Some local traffic @@ -197,7 +197,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.tester().clock().advance(duration1.negated()); fixture.loader().addQueryRateMeasurements(10, __ -> 10.0); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 6.8, 7.2, 28.8, + 8, 1, 7.3, 7.2, 28.8, fixture.autoscale()); // Enough local traffic to get half the votes @@ -207,7 +207,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.tester().clock().advance(duration2.negated()); fixture.loader().addQueryRateMeasurements(10, __ -> 50.0); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 3.0, 7.2, 28.8, + 8, 1, 3.2, 7.2, 28.8, fixture.autoscale()); // Mostly local @@ -217,7 +217,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.tester().clock().advance(duration3.negated()); fixture.loader().addQueryRateMeasurements(10, __ -> 90.0); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 2.2, 7.2, 28.8, + 8, 1, 2.3, 7.2, 28.8, fixture.autoscale()); // Local only @@ -227,7 +227,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.tester().clock().advance(duration4.negated()); fixture.loader().addQueryRateMeasurements(10, __ -> 100.0); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 2.1, 7.2, 28.8, + 8, 1, 2.2, 7.2, 28.8, fixture.autoscale()); // No group info, should be the same as the above @@ -237,7 +237,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.tester().clock().advance(duration5.negated()); fixture.loader().addQueryRateMeasurements(10, __ -> 100.0); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 2.1, 7.2, 28.8, + 8, 1, 2.2, 7.2, 28.8, fixture.autoscale()); // 40 query rate, no group info (for reference to the below) @@ -247,7 +247,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.tester().clock().advance(duration6.negated()); fixture.loader().addQueryRateMeasurements(10, __ -> 40.0); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 1.5, 7.2, 28.8, + 8, 1, 1.6, 7.2, 28.8, fixture.autoscale()); // Local query rate is too low but global is even lower so disregard it, giving the same as above @@ -257,7 +257,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.tester().clock().advance(duration7.negated()); fixture.loader().addQueryRateMeasurements(10, __ -> 40.0); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 1.5, 7.2, 28.8, + 8, 1, 1.6, 7.2, 28.8, fixture.autoscale()); // Local query rate is too low to be fully confident, and so is global but as it is slightly larger, incorporate it slightly @@ -267,7 +267,7 @@ public class AutoscalingUsingBcpGroupInfoTest { fixture.tester().clock().advance(duration8.negated()); fixture.loader().addQueryRateMeasurements(10, __ -> 40.0); fixture.tester().assertResources("Scaling up cpu using bcp group cpu info", - 8, 1, 1.8, 7.2, 28.8, + 8, 1, 1.9, 7.2, 28.8, fixture.autoscale()); } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModelTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModelTest.java index 8318ec65f05..cf450ca9a09 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModelTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModelTest.java @@ -43,17 +43,17 @@ public class ClusterModelTest { // No current traffic share: Ideal load is low but capped var model1 = clusterModel(new Status(0.0, 1.0), t -> t == 0 ? 10000.0 : 100.0, t -> 0.0); - assertEquals(0.32653061224489793, model1.idealLoad().cpu(), delta); + assertEquals(0.30612, model1.idealLoad().cpu(), delta); // Almost no current traffic share: Ideal load is low but capped var model2 = clusterModel(new Status(0.0001, 1.0), t -> t == 0 ? 10000.0 : 100.0, t -> 0.0); - assertEquals(0.32653061224489793, model2.idealLoad().cpu(), delta); + assertEquals(0.30612, model2.idealLoad().cpu(), delta); // Almost no traffic: Headroom impact is reduced due to uncertainty var model3 = clusterModel(new Status(0.0001, 1.0), t -> t == 0 ? 10000.0 : 1.0, t -> 0.0); - assertEquals(0.6465952717720751, model3.idealLoad().cpu(), delta); + assertEquals(0.606183, model3.idealLoad().cpu(), delta); } @Test @@ -61,22 +61,22 @@ public class ClusterModelTest { // No traffic data: Ideal load assumes 2 regions var model1 = clusterModel(new Status(0.0, 0.0), t -> t == 0 ? 10000.0 : 100.0, t -> 0.0); - assertEquals(0.16326530612244897, model1.idealLoad().cpu(), delta); + assertEquals(0.15306, model1.idealLoad().cpu(), delta); // No traffic: Ideal load is higher since we now know there is only one zone var model2 = clusterModel(new Status(0.0, 1.0), t -> t == 0 ? 10000.0 : 100.0, t -> 0.0); - assertEquals(0.32653061224489793, model2.idealLoad().cpu(), delta); + assertEquals(0.30612, model2.idealLoad().cpu(), delta); // Almost no current traffic: Similar number as above var model3 = clusterModel(new Status(0.0001, 1.0), t -> t == 0 ? 10000.0 : 100.0, t -> 0.0); - assertEquals(0.32653061224489793, model3.idealLoad().cpu(), delta); + assertEquals(0.30612, model3.idealLoad().cpu(), delta); // Low query rate: Impact of growth headroom is reduced due to uncertainty var model4 = clusterModel(new Status(0.0001, 1.0), t -> t == 0 ? 100.0 : 1.0, t -> 0.0); - assertEquals(0.6465952717720751, model4.idealLoad().cpu(), delta); + assertEquals(0.60618, model4.idealLoad().cpu(), delta); } private ClusterModel clusterModelWithNoData() { diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java index 51297a88cad..c53a4d88c01 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/ScalingSuggestionsMaintainerTest.java @@ -73,15 +73,15 @@ public class ScalingSuggestionsMaintainerTest { new TestMetric()); maintainer.maintain(); - assertEquals("8 nodes with [vcpu: 3.2, memory: 4.5 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", + assertEquals("8 nodes with [vcpu: 3.3, memory: 4.5 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", suggestionOf(app1, cluster1, tester).resources().get().toString()); - assertEquals("7 nodes with [vcpu: 4.1, memory: 5.3 Gb, disk: 16.5 Gb, bandwidth: 0.1 Gbps, architecture: any]", + assertEquals("7 nodes with [vcpu: 4.4, memory: 5.3 Gb, disk: 16.5 Gb, bandwidth: 0.1 Gbps, architecture: any]", suggestionOf(app2, cluster2, tester).resources().get().toString()); // Secondary suggestions - assertEquals("7 nodes with [vcpu: 3.7, memory: 4.5 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", + assertEquals("9 nodes with [vcpu: 2.9, memory: 4.5 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", suggestionsOf(app1, cluster1, tester).get(1).resources().get().toString()); - assertEquals("8 nodes with [vcpu: 3.6, memory: 4.7 Gb, disk: 14.2 Gb, bandwidth: 0.1 Gbps, architecture: any]", + assertEquals("8 nodes with [vcpu: 3.8, memory: 4.7 Gb, disk: 14.2 Gb, bandwidth: 0.1 Gbps, architecture: any]", suggestionsOf(app2, cluster2, tester).get(1).resources().get().toString()); // Utilization goes way down @@ -89,14 +89,14 @@ public class ScalingSuggestionsMaintainerTest { addMeasurements(0.10f, 0.10f, 0.10f, 0, 500, app1, tester.nodeRepository()); maintainer.maintain(); assertEquals("Suggestion stays at the peak value observed", - "8 nodes with [vcpu: 3.2, memory: 4.5 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", + "8 nodes with [vcpu: 3.3, memory: 4.5 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", suggestionOf(app1, cluster1, tester).resources().get().toString()); // Utilization is still way down and a week has passed tester.clock().advance(Duration.ofDays(7)); addMeasurements(0.10f, 0.10f, 0.10f, 0, 500, app1, tester.nodeRepository()); maintainer.maintain(); assertEquals("Peak suggestion has been outdated", - "3 nodes with [vcpu: 1.2, memory: 4.0 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", + "3 nodes with [vcpu: 1.3, memory: 4.0 Gb, disk: 10.0 Gb, bandwidth: 0.1 Gbps, architecture: any]", suggestionOf(app1, cluster1, tester).resources().get().toString()); assertTrue(shouldSuggest(app1, cluster1, tester)); diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java index 3f5992b2a64..98e8c60094c 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/NodeCandidateTest.java @@ -23,17 +23,17 @@ public class NodeCandidateTest { @Test public void testOrdering() { List<NodeCandidate> expected = List.of( - new NodeCandidate.ConcreteNodeCandidate(node("01", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), false, true, false, true, false, false), - new NodeCandidate.ConcreteNodeCandidate(node("02", Node.State.active), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false, false), - new NodeCandidate.ConcreteNodeCandidate(node("04", Node.State.reserved), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false, false), - new NodeCandidate.ConcreteNodeCandidate(node("03", Node.State.inactive), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false, false), - new NodeCandidate.ConcreteNodeCandidate(node("05", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.active)), true, true, false, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("06", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.ready)), true, true, false, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("07", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.provisioned)), true, true, false, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("08", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.failed)), true, true, false, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("09", Node.State.ready), false, new NodeResources(1, 1, 1, 1), Optional.empty(), true, true, false, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("10", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, true, false), - new NodeCandidate.ConcreteNodeCandidate(node("11", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, true, false) + new NodeCandidate.ConcreteNodeCandidate(node("01", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), false, true, false, false, false), + new NodeCandidate.ConcreteNodeCandidate(node("02", Node.State.active), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), + new NodeCandidate.ConcreteNodeCandidate(node("04", Node.State.reserved), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), + new NodeCandidate.ConcreteNodeCandidate(node("03", Node.State.inactive), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, false, false), + new NodeCandidate.ConcreteNodeCandidate(node("05", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.active)), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("06", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.ready)), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("07", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.provisioned)), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("08", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.of(node("host1", Node.State.failed)), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("09", Node.State.ready), false, new NodeResources(1, 1, 1, 1), Optional.empty(), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("10", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, true, false), + new NodeCandidate.ConcreteNodeCandidate(node("11", Node.State.ready), false, new NodeResources(2, 2, 2, 2), Optional.empty(), true, true, false, true, false) ); assertOrder(expected); } @@ -148,7 +148,7 @@ public class NodeCandidateTest { .ipConfig(IP.Config.of(List.of("::1"), List.of("::2"))) .build(); return new NodeCandidate.ConcreteNodeCandidate(node, false, totalHostResources.subtract(allocatedHostResources), Optional.of(parent), - false, exclusiveSwitch, false, false, true, false); + false, exclusiveSwitch, false, true, false); } private static NodeCandidate node(String hostname, NodeResources nodeResources, diff --git a/parent/pom.xml b/parent/pom.xml index 4003dd792f5..3299a9fb871 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -317,7 +317,7 @@ --> <groupId>org.openrewrite.maven</groupId> <artifactId>rewrite-maven-plugin</artifactId> - <version>5.28.0</version> + <version>5.29.0</version> <configuration> <activeRecipes> <recipe>org.openrewrite.java.testing.junit5.JUnit5BestPractices</recipe> @@ -327,7 +327,7 @@ <dependency> <groupId>org.openrewrite.recipe</groupId> <artifactId>rewrite-testing-frameworks</artifactId> - <version>2.6.0</version> + <version>2.7.0</version> </dependency> </dependencies> </plugin> @@ -1199,7 +1199,7 @@ See pluginManagement of rewrite-maven-plugin for more details --> <groupId>org.openrewrite.recipe</groupId> <artifactId>rewrite-recipe-bom</artifactId> - <version>2.9.0</version> + <version>2.10.0</version> <type>pom</type> <scope>import</scope> </dependency> diff --git a/searchlib/src/tests/attribute/attribute_test.cpp b/searchlib/src/tests/attribute/attribute_test.cpp index ff8641640a9..5e0392c7da5 100644 --- a/searchlib/src/tests/attribute/attribute_test.cpp +++ b/searchlib/src/tests/attribute/attribute_test.cpp @@ -907,7 +907,7 @@ AttributeTest::testSingle() AttributePtr ptr = createAttribute("sv-post-int32", cfg); ptr->updateStat(true); EXPECT_EQ(338972u, ptr->getStatus().getAllocated()); - EXPECT_EQ(101632u, ptr->getStatus().getUsed()); + EXPECT_EQ(101512u, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testSingle<IntegerAttribute, AttributeVector::largeint_t, int32_t>(ptr, values); } @@ -929,7 +929,7 @@ AttributeTest::testSingle() AttributePtr ptr = createAttribute("sv-post-float", cfg); ptr->updateStat(true); EXPECT_EQ(338972u, ptr->getStatus().getAllocated()); - EXPECT_EQ(101632u, ptr->getStatus().getUsed()); + EXPECT_EQ(101512u, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testSingle<FloatingPointAttribute, double, float>(ptr, values); } @@ -942,7 +942,7 @@ AttributeTest::testSingle() AttributePtr ptr = createAttribute("sv-string", Config(BasicType::STRING, CollectionType::SINGLE)); ptr->updateStat(true); EXPECT_EQ(116528u + sizeof_large_string_entry, ptr->getStatus().getAllocated()); - EXPECT_EQ(52844u + sizeof_large_string_entry, ptr->getStatus().getUsed()); + EXPECT_EQ(52684u + sizeof_large_string_entry, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testSingle<StringAttribute, string, string>(ptr, values); } @@ -952,7 +952,7 @@ AttributeTest::testSingle() AttributePtr ptr = createAttribute("sv-fs-string", cfg); ptr->updateStat(true); EXPECT_EQ(344848u + sizeof_large_string_entry, ptr->getStatus().getAllocated()); - EXPECT_EQ(104556u + sizeof_large_string_entry, ptr->getStatus().getUsed()); + EXPECT_EQ(104300u + sizeof_large_string_entry, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testSingle<StringAttribute, string, string>(ptr, values); } @@ -1083,8 +1083,8 @@ AttributeTest::testArray() { AttributePtr ptr = createAttribute("a-int32", Config(BasicType::INT32, CollectionType::ARRAY)); ptr->updateStat(true); - EXPECT_EQ(297952u, ptr->getStatus().getAllocated()); - EXPECT_EQ(256092u, ptr->getStatus().getUsed()); + EXPECT_EQ(293856u, ptr->getStatus().getAllocated()); + EXPECT_EQ(253668u, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values); } @@ -1093,8 +1093,8 @@ AttributeTest::testArray() cfg.setFastSearch(true); AttributePtr ptr = createAttribute("flags", cfg); ptr->updateStat(true); - EXPECT_EQ(297952u, ptr->getStatus().getAllocated()); - EXPECT_EQ(256092u, ptr->getStatus().getUsed()); + EXPECT_EQ(293856u, ptr->getStatus().getAllocated()); + EXPECT_EQ(253668u, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values); } @@ -1103,8 +1103,8 @@ AttributeTest::testArray() cfg.setFastSearch(true); AttributePtr ptr = createAttribute("a-fs-int32", cfg); ptr->updateStat(true); - EXPECT_EQ(654588u, ptr->getStatus().getAllocated()); - EXPECT_EQ(357744u, ptr->getStatus().getUsed()); + EXPECT_EQ(650492u, ptr->getStatus().getAllocated()); + EXPECT_EQ(355200u, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testArray<IntegerAttribute, AttributeVector::largeint_t>(ptr, values); } @@ -1122,8 +1122,8 @@ AttributeTest::testArray() cfg.setFastSearch(true); AttributePtr ptr = createAttribute("a-fs-float", cfg); ptr->updateStat(true); - EXPECT_EQ(654588u, ptr->getStatus().getAllocated()); - EXPECT_EQ(357744u, ptr->getStatus().getUsed()); + EXPECT_EQ(650492u, ptr->getStatus().getAllocated()); + EXPECT_EQ(355200u, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testArray<FloatingPointAttribute, double>(ptr, values); } @@ -1134,8 +1134,8 @@ AttributeTest::testArray() { AttributePtr ptr = createAttribute("a-string", Config(BasicType::STRING, CollectionType::ARRAY)); ptr->updateStat(true); - EXPECT_EQ(410256u + sizeof_large_string_entry, ptr->getStatus().getAllocated()); - EXPECT_EQ(308936u + sizeof_large_string_entry, ptr->getStatus().getUsed()); + EXPECT_EQ(406160u + sizeof_large_string_entry, ptr->getStatus().getAllocated()); + EXPECT_EQ(306352u + sizeof_large_string_entry, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testArray<StringAttribute, string>(ptr, values); } @@ -1144,8 +1144,8 @@ AttributeTest::testArray() cfg.setFastSearch(true); AttributePtr ptr = createAttribute("afs-string", cfg); ptr->updateStat(true); - EXPECT_EQ(660464u + sizeof_large_string_entry, ptr->getStatus().getAllocated()); - EXPECT_EQ(360668u + sizeof_large_string_entry, ptr->getStatus().getUsed()); + EXPECT_EQ(656368u + sizeof_large_string_entry, ptr->getStatus().getAllocated()); + EXPECT_EQ(357988u + sizeof_large_string_entry, ptr->getStatus().getUsed()); addDocs(ptr, numDocs); testArray<StringAttribute, string>(ptr, values); } diff --git a/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp b/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp index d67757a3811..0c60b376361 100644 --- a/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp +++ b/searchlib/src/tests/attribute/extendattributes/extendattribute_test.cpp @@ -224,7 +224,7 @@ void ExtendAttributeTest::testExtendRaw(AttributeVector& attr) void ExtendAttributeTest::testExtendTensor(AttributeVector& attr) { - std::vector<double> empty_cells{}; + std::vector<double> empty_cells{0, 0}; std::vector<double> spec0_dense_cells{1.0, 2.0}; std::vector<double> spec0_mixed_cells0{3.0, 4.0}; std::vector<double> spec0_mixed_cells1{5.0, 6.0}; diff --git a/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp b/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp index 1b51ba90f7c..7bd82ffdcad 100644 --- a/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp +++ b/searchlib/src/tests/memoryindex/memory_index/memory_index_test.cpp @@ -469,7 +469,7 @@ TEST(MemoryIndexTest, require_that_num_docs_and_doc_id_limit_is_returned) TEST(MemoryIndexTest, require_that_we_understand_the_memory_footprint) { constexpr size_t BASE_ALLOCATED = 360936u; - constexpr size_t BASE_USED = 150804u; + constexpr size_t BASE_USED = 150676u; { MySetup setup; Index index(setup); diff --git a/searchlib/src/tests/predicate/document_features_store_test.cpp b/searchlib/src/tests/predicate/document_features_store_test.cpp index 0e77a1be878..3d479a6d39a 100644 --- a/searchlib/src/tests/predicate/document_features_store_test.cpp +++ b/searchlib/src/tests/predicate/document_features_store_test.cpp @@ -175,18 +175,19 @@ TEST("require that both features and ranges are removed by 'remove'") { } TEST("require that both features and ranges counts towards memory usage") { + constexpr size_t BASE_USED = 557152u; DocumentFeaturesStore features_store(10); - EXPECT_EQUAL(562024u, features_store.getMemoryUsage().usedBytes()); + EXPECT_EQUAL(BASE_USED, features_store.getMemoryUsage().usedBytes()); PredicateTreeAnnotations annotations; annotations.features.push_back(PredicateHash::hash64("foo=100-199")); features_store.insert(annotations, doc_id); - EXPECT_EQUAL(562376u, features_store.getMemoryUsage().usedBytes()); + EXPECT_EQUAL(BASE_USED + 352u, features_store.getMemoryUsage().usedBytes()); annotations.features.clear(); annotations.range_features.push_back({"foo", 100, 199}); features_store.insert(annotations, doc_id + 1); - EXPECT_EQUAL(562480u, features_store.getMemoryUsage().usedBytes()); + EXPECT_EQUAL(BASE_USED + 456u, features_store.getMemoryUsage().usedBytes()); } TEST("require that DocumentFeaturesStore can be serialized") { @@ -212,21 +213,22 @@ TEST("require that DocumentFeaturesStore can be serialized") { } TEST("require that serialization cleans up wordstore") { + constexpr size_t BASE_USED = 557592u; DocumentFeaturesStore features_store(10); PredicateTreeAnnotations annotations; annotations.range_features.push_back({"foo", 100, 199}); features_store.insert(annotations, doc_id); - EXPECT_EQUAL(562464u, features_store.getMemoryUsage().usedBytes()); + EXPECT_EQUAL(BASE_USED, features_store.getMemoryUsage().usedBytes()); annotations.range_features.push_back({"bar", 100, 199}); features_store.insert(annotations, doc_id + 1); - EXPECT_EQUAL(562524u, features_store.getMemoryUsage().usedBytes()); + EXPECT_EQUAL(BASE_USED +60u, features_store.getMemoryUsage().usedBytes()); features_store.remove(doc_id + 1); - EXPECT_EQUAL(562524u, features_store.getMemoryUsage().usedBytes()); + EXPECT_EQUAL(BASE_USED + 60u, features_store.getMemoryUsage().usedBytes()); vespalib::DataBuffer buffer; save_document_features_store(features_store, buffer); DocumentFeaturesStore features_store2(buffer); - EXPECT_EQUAL(562464u, features_store2.getMemoryUsage().usedBytes()); + EXPECT_EQUAL(BASE_USED, features_store2.getMemoryUsage().usedBytes()); } diff --git a/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp b/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp index 31b147c0b5c..d50677314df 100644 --- a/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp +++ b/searchlib/src/tests/tensor/hnsw_index/hnsw_index_test.cpp @@ -12,6 +12,7 @@ #include <vespa/searchlib/tensor/random_level_generator.h> #include <vespa/searchlib/tensor/inv_log_level_generator.h> #include <vespa/searchlib/tensor/subspace_type.h> +#include <vespa/searchlib/tensor/empty_subspace.h> #include <vespa/searchlib/tensor/vector_bundle.h> #include <vespa/searchlib/queryeval/global_filter.h> #include <vespa/vespalib/datastore/compaction_spec.h> @@ -49,6 +50,7 @@ private: using ArrayRef = vespalib::ConstArrayRef<FloatType>; mutable std::vector<Vector> _vectors; SubspaceType _subspace_type; + EmptySubspace _empty; mutable uint32_t _get_vector_count; mutable uint32_t _schedule_clear_tensor; mutable uint32_t _cleared_tensor_docid; @@ -57,6 +59,7 @@ public: MyDocVectorAccess() : _vectors(), _subspace_type(ValueType::make_type(get_cell_type<FloatType>(), {{"dims", 2}})), + _empty(_subspace_type), _get_vector_count(0), _schedule_clear_tensor(0), _cleared_tensor_docid(0) @@ -87,7 +90,7 @@ public: if (subspace < bundle.subspaces()) { return bundle.cells(subspace); } - return { nullptr, _subspace_type.cell_type(), 0 }; + return _empty.cells(); } VectorBundle get_vectors(uint32_t docid) const noexcept override { ArrayRef ref(_vectors[docid]); @@ -128,12 +131,12 @@ public: double min_rawscore() const noexcept override { return _real->min_rawscore(); } double calc(TypedCells rhs) const noexcept override { - EXPECT_TRUE(rhs.valid()); + EXPECT_FALSE(rhs.non_existing_attribute_value()); return _real->calc(rhs); } double calc_with_limit(TypedCells rhs, double limit) const noexcept override { - EXPECT_TRUE(rhs.valid()); + EXPECT_FALSE(rhs.non_existing_attribute_value()); return _real->calc_with_limit(rhs, limit); } }; @@ -152,12 +155,12 @@ public: ~MyDistanceFunctionFactory() override; std::unique_ptr<BoundDistanceFunction> for_query_vector(TypedCells lhs) override { - EXPECT_TRUE(lhs.valid()); + EXPECT_FALSE(lhs.non_existing_attribute_value()); return std::make_unique<MyBoundDistanceFunction>(_real->for_query_vector(lhs)); } std::unique_ptr<BoundDistanceFunction> for_insertion_vector(TypedCells lhs) override { - EXPECT_TRUE(lhs.valid()); + EXPECT_FALSE(lhs.non_existing_attribute_value()); return std::make_unique<MyBoundDistanceFunction>(_real->for_insertion_vector(lhs)); } }; diff --git a/searchlib/src/vespa/searchlib/attribute/posting_iterator_pack.cpp b/searchlib/src/vespa/searchlib/attribute/posting_iterator_pack.cpp index 93bc4735916..3bd1682c470 100644 --- a/searchlib/src/vespa/searchlib/attribute/posting_iterator_pack.cpp +++ b/searchlib/src/vespa/searchlib/attribute/posting_iterator_pack.cpp @@ -10,20 +10,13 @@ template <typename IteratorType, typename RefType> PostingIteratorPack<IteratorType, RefType>::~PostingIteratorPack() = default; template <typename IteratorType, typename RefType> -PostingIteratorPack<IteratorType, RefType>::PostingIteratorPack(std::vector<IteratorType> &&children) +PostingIteratorPack<IteratorType, RefType>::PostingIteratorPack(std::vector<IteratorType> &&children) noexcept : _children(std::move(children)) { assert(_children.size() <= std::numeric_limits<ref_t>::max()); } template <typename IteratorType, typename RefType> -bool -PostingIteratorPack<IteratorType, RefType>::can_handle_iterators(size_t num_iterators) -{ - return num_iterators <= std::numeric_limits<ref_t>::max(); -} - -template <typename IteratorType, typename RefType> std::unique_ptr<BitVector> PostingIteratorPack<IteratorType, RefType>::get_hits(uint32_t begin_id, uint32_t end_id) { BitVector::UP result(BitVector::create(begin_id, end_id)); @@ -48,14 +41,14 @@ PostingIteratorPack<IteratorType, RefType>::or_hits_into(BitVector &result, uint template <> int32_t -PostingIteratorPack<DocidIterator, uint16_t>::get_weight(ref_t, uint32_t) +PostingIteratorPack<DocidIterator, uint16_t>::get_weight(ref_t, uint32_t) noexcept { return 1; } template <> int32_t -PostingIteratorPack<DocidIterator, uint32_t>::get_weight(ref_t, uint32_t) +PostingIteratorPack<DocidIterator, uint32_t>::get_weight(ref_t, uint32_t) noexcept { return 1; } diff --git a/searchlib/src/vespa/searchlib/attribute/posting_iterator_pack.h b/searchlib/src/vespa/searchlib/attribute/posting_iterator_pack.h index 7c6b85dd3ec..ce0163dc293 100644 --- a/searchlib/src/vespa/searchlib/attribute/posting_iterator_pack.h +++ b/searchlib/src/vespa/searchlib/attribute/posting_iterator_pack.h @@ -23,16 +23,18 @@ public: PostingIteratorPack(PostingIteratorPack &&rhs) noexcept = default; PostingIteratorPack &operator=(PostingIteratorPack &&rhs) noexcept = default; - explicit PostingIteratorPack(std::vector<IteratorType> &&children); + explicit PostingIteratorPack(std::vector<IteratorType> &&children) noexcept; ~PostingIteratorPack(); - static bool can_handle_iterators(size_t num_iterators); + constexpr static bool can_handle_iterators(size_t num_iterators) noexcept { + return num_iterators <= std::numeric_limits<ref_t>::max(); + } - uint32_t get_docid(ref_t ref) const { + uint32_t get_docid(ref_t ref) const noexcept { return _children[ref].valid() ? _children[ref].getKey() : endDocId; } - uint32_t seek(ref_t ref, uint32_t docid) { + uint32_t seek(ref_t ref, uint32_t docid) noexcept { _children[ref].linearSeek(docid); if (__builtin_expect(_children[ref].valid(), true)) { return _children[ref].getKey(); @@ -40,7 +42,7 @@ public: return endDocId; } - int32_t get_weight(ref_t ref, uint32_t) { + int32_t get_weight(ref_t ref, uint32_t) noexcept { return _children[ref].getData(); } @@ -48,14 +50,14 @@ public: void or_hits_into(BitVector &result, uint32_t begin_id); ref_t size() const noexcept { return _children.size(); } - void initRange(uint32_t begin, uint32_t end) { + void initRange(uint32_t begin, uint32_t end) noexcept { (void) end; for (auto &child: _children) { child.lower_bound(begin); } } private: - uint32_t next(ref_t ref) { + uint32_t next(ref_t ref) noexcept { ++_children[ref]; return get_docid(ref); } diff --git a/searchlib/src/vespa/searchlib/features/mutable_dense_value_view.h b/searchlib/src/vespa/searchlib/features/mutable_dense_value_view.h index 4794de23b4a..52576841093 100644 --- a/searchlib/src/vespa/searchlib/features/mutable_dense_value_view.h +++ b/searchlib/src/vespa/searchlib/features/mutable_dense_value_view.h @@ -12,20 +12,20 @@ using namespace vespalib::eval; /** * A dense tensor with a cells reference that can be modified. */ -class MutableDenseValueView : public Value { +class MutableDenseValueView final : public Value { private: const ValueType _type; TypedCells _cells; public: - MutableDenseValueView(const ValueType &type_in); - void setCells(TypedCells cells_in) { + explicit MutableDenseValueView(const ValueType &type_in); + void setCells(TypedCells cells_in) noexcept { assert(cells_in.type == _type.cell_type()); _cells = cells_in; } - const ValueType &type() const final override { return _type; } - TypedCells cells() const final override { return _cells; } - const Index &index() const final override { return TrivialIndex::get(); } - vespalib::MemoryUsage get_memory_usage() const final override { + const ValueType &type() const override { return _type; } + TypedCells cells() const override { return _cells; } + const Index &index() const override { return TrivialIndex::get(); } + vespalib::MemoryUsage get_memory_usage() const override { return self_memory_usage<MutableDenseValueView>(); } }; diff --git a/searchlib/src/vespa/searchlib/grouping/collect.cpp b/searchlib/src/vespa/searchlib/grouping/collect.cpp index d0a9a38bf7d..464362602f2 100644 --- a/searchlib/src/vespa/searchlib/grouping/collect.cpp +++ b/searchlib/src/vespa/searchlib/grouping/collect.cpp @@ -1,7 +1,6 @@ // Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "collect.h" -#include <vespa/vespalib/util/array.hpp> #include <cassert> using namespace search::expression; @@ -48,8 +47,7 @@ Collect::~Collect() assert((_aggrBacking.size() % _aggregatorSize) == 0); for (size_t i(0), m(_aggrBacking.size()/_aggregatorSize); i < m; i++) { uint8_t * base(&_aggrBacking[ i * _aggregatorSize]); - for (size_t j(0), k(_aggregator.size()); j < k; j++) { - ResultAccessor & r = _aggregator[j]; + for (auto & r : _aggregator) { r.destroy(base); } } @@ -74,8 +72,8 @@ void Collect::collect(GroupRef gr, uint32_t docId, double rank) { uint8_t * base(&_aggrBacking[getAggrBase(gr)]); - for (size_t i(0), m(_aggregator.size()); i < m; i++) { - _aggregator[i].aggregate(base, docId, rank); + for (auto & i : _aggregator) { + i.aggregate(base, docId, rank); } } @@ -86,8 +84,7 @@ Collect::createCollectors(GroupRef gr) if (offset == _aggrBacking.size()) { _aggrBacking.resize(getAggrBase(GroupRef(gr.getRef() + 1))); uint8_t * base(&_aggrBacking[offset]); - for (size_t i(0), m(_aggregator.size()); i < m; i++) { - ResultAccessor & r = _aggregator[i]; + for (auto & r : _aggregator) { r.create(base); } } diff --git a/searchlib/src/vespa/searchlib/grouping/collect.h b/searchlib/src/vespa/searchlib/grouping/collect.h index 3566d21f821..932cf559156 100644 --- a/searchlib/src/vespa/searchlib/grouping/collect.h +++ b/searchlib/src/vespa/searchlib/grouping/collect.h @@ -13,7 +13,7 @@ public: Collect(const Collect &) = delete; Collect & operator = (const Collect &) = delete; protected: - Collect(const aggregation::Group & protoType); + explicit Collect(const aggregation::Group & protoType); ~Collect(); void preFill(GroupRef gr, const aggregation::Group & r); void createCollectors(GroupRef gr); @@ -55,9 +55,9 @@ private: */ class ResultAccessor { public: - ResultAccessor() : _bluePrint(NULL), _aggregator(NULL), _offset(0) { } + ResultAccessor() noexcept : _bluePrint(nullptr), _aggregator(nullptr), _offset(0) { } ResultAccessor(const aggregation::AggregationResult & aggregator, size_t offset); - void setResult(const expression::ResultNode & result, uint8_t * base) { + void setResult(const expression::ResultNode & result, uint8_t * base) const { result.encode(base+_offset); } const expression::ResultNode & getResult(expression::ResultNode & result, const uint8_t * base) const { @@ -86,8 +86,8 @@ private: mutable vespalib::IdentifiablePtr<aggregation::AggregationResult> _aggregator; uint32_t _offset; }; - using AggregatorBacking = vespalib::Array<uint8_t>; - using ResultAccessorList = vespalib::Array<ResultAccessor>; + using AggregatorBacking = std::vector<uint8_t>; + using ResultAccessorList = std::vector<ResultAccessor>; class SortInfo { public: SortInfo() noexcept : _index(0), _sign(1) { } @@ -98,10 +98,10 @@ private: uint8_t _index; // Which index in the aggragators should be used for sorting this level. int8_t _sign; // And which way. positive number -> ascending, negative number descending. }; - size_t _aggregatorSize; // This is the bytesize required to store the aggrgate values per bucket. - ResultAccessorList _aggregator; // These are the accessors to use when accessing the results. - AggregatorBacking _aggrBacking; // This is the storage for the accessors. - std::vector<SortInfo> _sortInfo; // Generated cheap sortInfo, to avoid accessing more complicated data. + size_t _aggregatorSize; // This is the bytesize required to store the aggrgate values per bucket. + ResultAccessorList _aggregator; // These are the accessors to use when accessing the results. + AggregatorBacking _aggrBacking; // This is the storage for the accessors. + std::vector<SortInfo> _sortInfo; // Generated cheap sortInfo, to avoid accessing more complicated data. }; } diff --git a/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_search.cpp b/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_search.cpp index f3028f5159a..9e887b9d0f7 100644 --- a/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_search.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/wand/parallel_weak_and_search.cpp @@ -14,7 +14,6 @@ using vespalib::make_string; namespace search::queryeval { using MatchParams = ParallelWeakAndSearch::MatchParams; -using RankParams = ParallelWeakAndSearch::RankParams; namespace wand { @@ -22,7 +21,7 @@ namespace { bool should_monitor_wand() { return LOG_WOULD_LOG(spam); } } template <typename VectorizedTerms, typename FutureHeap, typename PastHeap, bool IS_STRICT> -class ParallelWeakAndSearchImpl : public ParallelWeakAndSearch +class ParallelWeakAndSearchImpl final : public ParallelWeakAndSearch { private: fef::TermFieldMatchData &_tfmd; @@ -120,8 +119,7 @@ insertMonitoringSearchIterator(const wand::Terms &terms) for (size_t i = 0; i < terms.size(); ++i) { wand::Term &t = retval[i]; t.search = new MonitoringSearchIterator - (make_string("w%d:e%u:m%" PRId64 "", - t.weight, t.estHits, DotProductScorer::calculateMaxScore(t)), + (make_string("w%d:e%u:m%" PRId64 "", t.weight, t.estHits, DotProductScorer::calculateMaxScore(t)), SearchIterator::UP(t.search), true); } return retval; @@ -167,11 +165,9 @@ ParallelWeakAndSearch::createArrayWand(const Terms &terms, RankParams &&rankParams, bool strict) { - if (strict) { - return wand::createWand<vespalib::LeftArrayHeap, vespalib::RightArrayHeap, true>(terms, matchParams, std::move(rankParams)); - } else { - return wand::createWand<vespalib::LeftArrayHeap, vespalib::RightArrayHeap, false>(terms, matchParams, std::move(rankParams)); - } + return strict + ? wand::createWand<vespalib::LeftArrayHeap, vespalib::RightArrayHeap, true>(terms, matchParams, std::move(rankParams)) + : wand::createWand<vespalib::LeftArrayHeap, vespalib::RightArrayHeap, false>(terms, matchParams, std::move(rankParams)); } SearchIterator::UP @@ -180,11 +176,9 @@ ParallelWeakAndSearch::createHeapWand(const Terms &terms, RankParams &&rankParams, bool strict) { - if (strict) { - return wand::createWand<vespalib::LeftHeap, vespalib::RightHeap, true>(terms, matchParams, std::move(rankParams)); - } else { - return wand::createWand<vespalib::LeftHeap, vespalib::RightHeap, false>(terms, matchParams, std::move(rankParams)); - } + return strict + ? wand::createWand<vespalib::LeftHeap, vespalib::RightHeap, true>(terms, matchParams, std::move(rankParams)) + : wand::createWand<vespalib::LeftHeap, vespalib::RightHeap, false>(terms, matchParams, std::move(rankParams)); } SearchIterator::UP @@ -193,11 +187,9 @@ ParallelWeakAndSearch::create(const Terms &terms, RankParams &&rankParams, bool strict) { - if (terms.size() < 128) { - return createArrayWand(terms, matchParams, std::move(rankParams), strict); - } else { - return createHeapWand(terms, matchParams, std::move(rankParams), strict); - } + return (terms.size() < 128) + ? createArrayWand(terms, matchParams, std::move(rankParams), strict) + : createHeapWand(terms, matchParams, std::move(rankParams), strict); } //----------------------------------------------------------------------------- @@ -206,9 +198,11 @@ namespace { template <typename VectorizedTerms, typename FutureHeap, typename PastHeap> SearchIterator::UP create_helper(search::fef::TermFieldMatchData &tfmd, VectorizedTerms &&terms, const MatchParams ¶ms, bool strict) { - return (strict) - ? SearchIterator::UP(new wand::ParallelWeakAndSearchImpl<VectorizedTerms, FutureHeap, PastHeap, true>(tfmd, std::move(terms), params)) - : SearchIterator::UP( new wand::ParallelWeakAndSearchImpl<VectorizedTerms, FutureHeap, PastHeap, false>(tfmd, std::move(terms), params)); + if (strict) { + return std::make_unique<wand::ParallelWeakAndSearchImpl<VectorizedTerms, FutureHeap, PastHeap, true>>(tfmd, std::move(terms), params); + } else { + return std::make_unique<wand::ParallelWeakAndSearchImpl<VectorizedTerms, FutureHeap, PastHeap, false>>(tfmd, std::move(terms), params); + } } template <typename VectorizedTerms> @@ -236,19 +230,20 @@ ParallelWeakAndSearch::create(search::fef::TermFieldMatchData &tfmd, // reverse-wrap direct iterators into old API to be compatible with monitoring fef::MatchDataLayout layout; std::vector<fef::TermFieldHandle> handles; + handles.reserve(weights.size()); for (size_t i = 0; i < weights.size(); ++i) { handles.push_back(layout.allocTermField(tfmd.getFieldId())); } fef::MatchData::UP childrenMatchData = layout.createMatchData(); assert(childrenMatchData->getNumTermFields() == dict_entries.size()); wand::Terms terms; + terms.reserve(dict_entries.size()); for (size_t i = 0; i < dict_entries.size(); ++i) { - terms.push_back(wand::Term(new DocidWithWeightSearchIterator(*(childrenMatchData->resolveTermField(handles[i])), attr, dict_entries[i]), - weights[i], - dict_entries[i].posting_size, - childrenMatchData->resolveTermField(handles[i]))); + terms.emplace_back(new DocidWithWeightSearchIterator(*(childrenMatchData->resolveTermField(handles[i])), attr, dict_entries[i]), + weights[i], + dict_entries[i].posting_size, + childrenMatchData->resolveTermField(handles[i])); } - assert(terms.size() == dict_entries.size()); return create(terms, matchParams, RankParams(tfmd, std::move(childrenMatchData)), strict); } } diff --git a/searchlib/src/vespa/searchlib/queryeval/wand/wand_parts.h b/searchlib/src/vespa/searchlib/queryeval/wand/wand_parts.h index 9431b527510..ed8d4b4e4ac 100644 --- a/searchlib/src/vespa/searchlib/queryeval/wand/wand_parts.h +++ b/searchlib/src/vespa/searchlib/queryeval/wand/wand_parts.h @@ -26,7 +26,6 @@ using ref_t = uint16_t; using Attr = IDirectPostingStore; using AttrDictEntry = Attr::LookupResult; -using AttrDictEntries = std::vector<AttrDictEntry>; //----------------------------------------------------------------------------- @@ -55,14 +54,14 @@ struct Term { namespace { struct Ident { - template <typename T> T operator()(const T &t) const { return t; } + template <typename T> T operator()(const T &t) const noexcept { return t; } }; struct NumericOrder { size_t my_size; - NumericOrder(size_t my_size_in) : my_size(my_size_in) {} - size_t size() const { return my_size; } - ref_t operator[](size_t idx) const { return idx; } + explicit NumericOrder(size_t my_size_in) noexcept : my_size(my_size_in) {} + size_t size() const noexcept { return my_size; } + ref_t operator[](size_t idx) const noexcept { return idx; } }; template <typename F, typename Order> @@ -84,25 +83,25 @@ int32_t get_max_weight(const SearchIterator &search) { struct TermInput { const Terms &terms; - TermInput(const Terms &terms_in) : terms(terms_in) {} - size_t size() const { return terms.size(); } - int32_t get_weight(ref_t ref) const { return terms[ref].weight; } - uint32_t get_est_hits(ref_t ref) const { return terms[ref].estHits; } - int32_t get_max_weight(ref_t ref) const { return ::search::queryeval::wand::get_max_weight(*(terms[ref].search)); } - docid_t get_initial_docid(ref_t ref) const { return terms[ref].search->getDocId(); } + explicit TermInput(const Terms &terms_in) noexcept : terms(terms_in) {} + size_t size() const noexcept { return terms.size(); } + int32_t get_weight(ref_t ref) const noexcept { return terms[ref].weight; } + uint32_t get_est_hits(ref_t ref) const noexcept { return terms[ref].estHits; } + int32_t get_max_weight(ref_t ref) const noexcept { return ::search::queryeval::wand::get_max_weight(*(terms[ref].search)); } + docid_t get_initial_docid(ref_t ref) const noexcept { return terms[ref].search->getDocId(); } }; struct AttrInput { const std::vector<int32_t> &weights; const std::vector<IDirectPostingStore::LookupResult> &dict_entries; AttrInput(const std::vector<int32_t> &weights_in, - const std::vector<IDirectPostingStore::LookupResult> &dict_entries_in) + const std::vector<IDirectPostingStore::LookupResult> &dict_entries_in) noexcept : weights(weights_in), dict_entries(dict_entries_in) {} - size_t size() const { return weights.size(); } - int32_t get_weight(ref_t ref) const { return weights[ref]; } - uint32_t get_est_hits(ref_t ref) const { return dict_entries[ref].posting_size; } - int32_t get_max_weight(ref_t ref) const { return dict_entries[ref].max_weight; } - docid_t get_initial_docid(ref_t) const { return SearchIterator::beginId(); } + size_t size() const noexcept { return weights.size(); } + int32_t get_weight(ref_t ref) const noexcept { return weights[ref]; } + uint32_t get_est_hits(ref_t ref) const noexcept { return dict_entries[ref].posting_size; } + int32_t get_max_weight(ref_t ref) const noexcept { return dict_entries[ref].max_weight; } + docid_t get_initial_docid(ref_t) const noexcept { return SearchIterator::beginId(); } }; template <typename Input> @@ -111,7 +110,7 @@ struct MaxSkipOrder { const Input &input; const std::vector<score_t> &max_score; MaxSkipOrder(docid_t docIdLimit, const Input &input_in, - const std::vector<score_t> &max_score_in) + const std::vector<score_t> &max_score_in) noexcept : estNumDocs(1.0), input(input_in), max_score(max_score_in) { estNumDocs = std::max(estNumDocs, docIdLimit - 1.0); @@ -119,10 +118,10 @@ struct MaxSkipOrder { estNumDocs = std::max(estNumDocs, (double)input.get_est_hits(i)); } } - double p_not_hit(double estHits) const { + double p_not_hit(double estHits) const noexcept { return ((estNumDocs - estHits) / (estNumDocs)); } - bool operator()(ref_t a, ref_t b) const { + bool operator()(ref_t a, ref_t b) const noexcept { return ((p_not_hit(input.get_est_hits(a)) * max_score[a]) > (p_not_hit(input.get_est_hits(b)) * max_score[b])); } }; @@ -158,7 +157,7 @@ private: IteratorPack _iteratorPack; public: - VectorizedState(); + VectorizedState() noexcept; VectorizedState(VectorizedState &&) noexcept; VectorizedState & operator=(VectorizedState &&) noexcept; ~VectorizedState(); @@ -184,7 +183,7 @@ public: }; template <typename IteratorPack> -VectorizedState<IteratorPack>::VectorizedState() +VectorizedState<IteratorPack>::VectorizedState() noexcept : _docId(), _weight(), _maxScore(), @@ -292,10 +291,10 @@ struct VectorizedAttributeTerms : VectorizedState<DocidWithWeightIteratorPack> { **/ struct DocIdOrder { const docid_t *termPos; - DocIdOrder(docid_t *pos) : termPos(pos) {} - bool at_end(ref_t ref) const { return termPos[ref] == search::endDocId; } - docid_t get_pos(ref_t ref) const { return termPos[ref]; } - bool operator()(ref_t a, ref_t b) const { + explicit DocIdOrder(docid_t *pos) noexcept : termPos(pos) {} + bool at_end(ref_t ref) const noexcept { return termPos[ref] == search::endDocId; } + docid_t get_pos(ref_t ref) const noexcept { return termPos[ref]; } + bool operator()(ref_t a, ref_t b) const noexcept { return (termPos[a] < termPos[b]); } }; @@ -358,7 +357,7 @@ DualHeap<FutureHeap, PastHeap>::DualHeap(const DocIdOrder &futureCmp, size_t siz } template <typename FutureHeap, typename PastHeap> -DualHeap<FutureHeap, PastHeap>::~DualHeap() { } +DualHeap<FutureHeap, PastHeap>::~DualHeap() = default; template <typename FutureHeap, typename PastHeap> void @@ -399,11 +398,11 @@ DualHeap<FutureHeap, PastHeap>::stringify() const { struct TermFrequencyScorer { // weight * idf, scaled to fixedpoint - static score_t calculateMaxScore(double estHits, double weight) { + static score_t calculateMaxScore(double estHits, double weight) noexcept { return (score_t) (TermFrequencyScorer_TERM_SCORE_FACTOR * weight / (1.0 + log(1.0 + (estHits / 1000.0)))); } - static score_t calculateMaxScore(const Term &term) { + static score_t calculateMaxScore(const Term &term) noexcept { return calculateMaxScore(term.estHits, term.weight) + 1; } @@ -424,9 +423,9 @@ struct DotProductScorer static score_t calculateMaxScore(const Term &term) { int32_t maxWeight = std::numeric_limits<int32_t>::max(); const PostingInfo *postingInfo = term.search->getPostingInfo(); - if (postingInfo != NULL) { - const MinMaxPostingInfo *minMax = dynamic_cast<const MinMaxPostingInfo *>(postingInfo); - if (minMax != NULL) { + if (postingInfo != nullptr) { + const auto *minMax = dynamic_cast<const MinMaxPostingInfo *>(postingInfo); + if (minMax != nullptr) { maxWeight = minMax->getMaxWeight(); } } diff --git a/searchlib/src/vespa/searchlib/queryeval/wand/weak_and_search.cpp b/searchlib/src/vespa/searchlib/queryeval/wand/weak_and_search.cpp index f915a7df335..375a6598b49 100644 --- a/searchlib/src/vespa/searchlib/queryeval/wand/weak_and_search.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/wand/weak_and_search.cpp @@ -109,9 +109,9 @@ SearchIterator::UP WeakAndSearch::createArrayWand(const Terms &terms, uint32_t n, bool strict) { if (strict) { - return SearchIterator::UP(new wand::WeakAndSearchLR<vespalib::LeftArrayHeap, vespalib::RightArrayHeap, true>(terms, n)); + return std::make_unique<wand::WeakAndSearchLR<vespalib::LeftArrayHeap, vespalib::RightArrayHeap, true>>(terms, n); } else { - return SearchIterator::UP(new wand::WeakAndSearchLR<vespalib::LeftArrayHeap, vespalib::RightArrayHeap, false>(terms, n)); + return std::make_unique<wand::WeakAndSearchLR<vespalib::LeftArrayHeap, vespalib::RightArrayHeap, false>>(terms, n); } } @@ -119,9 +119,9 @@ SearchIterator::UP WeakAndSearch::createHeapWand(const Terms &terms, uint32_t n, bool strict) { if (strict) { - return SearchIterator::UP(new wand::WeakAndSearchLR<vespalib::LeftHeap, vespalib::RightHeap, true>(terms, n)); + return std::make_unique<wand::WeakAndSearchLR<vespalib::LeftHeap, vespalib::RightHeap, true>>(terms, n); } else { - return SearchIterator::UP(new wand::WeakAndSearchLR<vespalib::LeftHeap, vespalib::RightHeap, false>(terms, n)); + return std::make_unique<wand::WeakAndSearchLR<vespalib::LeftHeap, vespalib::RightHeap, false>>(terms, n); } } diff --git a/searchlib/src/vespa/searchlib/queryeval/wand/weak_and_search.h b/searchlib/src/vespa/searchlib/queryeval/wand/weak_and_search.h index cda5f4c4232..6a56a04887c 100644 --- a/searchlib/src/vespa/searchlib/queryeval/wand/weak_and_search.h +++ b/searchlib/src/vespa/searchlib/queryeval/wand/weak_and_search.h @@ -2,11 +2,10 @@ #pragma once -#include <vespa/searchlib/queryeval/searchiterator.h> #include "wand_parts.h" +#include <vespa/searchlib/queryeval/searchiterator.h> -namespace search { -namespace queryeval { +namespace search::queryeval { struct WeakAndSearch : SearchIterator { using Terms = wand::Terms; @@ -21,6 +20,4 @@ struct WeakAndSearch : SearchIterator { static SearchIterator::UP create(const Terms &terms, uint32_t n, bool strict); }; -} // namespace queryeval -} // namespace search - +} diff --git a/searchlib/src/vespa/searchlib/tensor/distance_calculator.h b/searchlib/src/vespa/searchlib/tensor/distance_calculator.h index 7ff9448c5af..1bdd3b39711 100644 --- a/searchlib/src/vespa/searchlib/tensor/distance_calculator.h +++ b/searchlib/src/vespa/searchlib/tensor/distance_calculator.h @@ -45,7 +45,7 @@ public: if (has_single_subspace) { auto cells = _attr_tensor.get_vector(docid, 0); double min_rawscore = _dist_fun->min_rawscore(); - if ( ! cells.valid() ) [[unlikely]] { + if ( cells.non_existing_attribute_value() ) [[unlikely]] { return min_rawscore; } return std::max(min_rawscore, _dist_fun->to_rawscore(_dist_fun->calc(cells))); @@ -66,7 +66,7 @@ public: double calc_with_limit(uint32_t docid, double limit) const noexcept { if (has_single_subspace) { auto cells = _attr_tensor.get_vector(docid, 0); - if ( ! cells.valid() ) [[unlikely]] { + if ( cells.non_existing_attribute_value() ) [[unlikely]] { return std::numeric_limits<double>::max(); } return _dist_fun->calc_with_limit(cells, limit); diff --git a/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp b/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp index a7168b5eae6..b0fa1a682db 100644 --- a/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp +++ b/searchlib/src/vespa/searchlib/tensor/empty_subspace.cpp @@ -3,6 +3,8 @@ #include "empty_subspace.h" #include "subspace_type.h" +using vespalib::eval::TypedCells; + namespace search::tensor { EmptySubspace::EmptySubspace(const SubspaceType& type) @@ -10,8 +12,7 @@ EmptySubspace::EmptySubspace(const SubspaceType& type) _cells() { _empty_space.resize(type.mem_size()); - // Set size to zero to signal empty/invalid subspace - _cells = vespalib::eval::TypedCells(_empty_space.data(), type.cell_type(), 0); + _cells = TypedCells::create_non_existing_attribute_value(_empty_space.data(), type.cell_type(), type.size()); } EmptySubspace::~EmptySubspace() = default; diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_graph.cpp b/searchlib/src/vespa/searchlib/tensor/hnsw_graph.cpp index 16e2af0ad97..4d57b87d257 100644 --- a/searchlib/src/vespa/searchlib/tensor/hnsw_graph.cpp +++ b/searchlib/src/vespa/searchlib/tensor/hnsw_graph.cpp @@ -102,10 +102,9 @@ HnswGraph<type>::histograms() const for (size_t i = 0; i < num_nodes; ++i) { auto levels_ref = acquire_levels_ref(i); if (levels_ref.valid()) { - uint32_t levels = 0; uint32_t l0links = 0; auto level_array = levels_store.get(levels_ref); - levels = level_array.size(); + uint32_t levels = level_array.size(); if (levels > 0) { auto links_ref = level_array[0].load_acquire(); auto link_array = links_store.get(links_ref); diff --git a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp index cdc3e81782a..1db688156e0 100644 --- a/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp +++ b/searchlib/src/vespa/searchlib/tensor/hnsw_index.cpp @@ -183,7 +183,7 @@ bool HnswIndex<type>::have_closer_distance(HnswTraversalCandidate candidate, const HnswTraversalCandidateVector& result) const { auto candidate_vector = get_vector(candidate.nodeid); - if (!candidate_vector.valid()) { + if (candidate_vector.non_existing_attribute_value()) { /* * We are in a read thread and the write thread has removed the * tensor for the candidate. Return true to prevent the candidate @@ -319,7 +319,7 @@ namespace { double calc_distance_helper(const BoundDistanceFunction &df, vespalib::eval::TypedCells rhs) { - if (!rhs.valid()) [[unlikely]] { + if (rhs.non_existing_attribute_value()) [[unlikely]] { /* * We are in a read thread and the write thread has removed the * tensor. diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java index 92a9c4df27d..75f77409447 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/ClientFeederV3.java @@ -33,7 +33,7 @@ import java.util.logging.Logger; * avoid using a threadpool that has no effect with all the extra that comes with it. V2 has one instance per thread * on the client, while this is one instance for all threads. * - * @author dybis + * @author Haakon Dybdahl */ class ClientFeederV3 { diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/DocumentOperationMessageV3.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/DocumentOperationMessageV3.java index 8b3f9e45a79..e5f826b8913 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/DocumentOperationMessageV3.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/DocumentOperationMessageV3.java @@ -11,7 +11,7 @@ import com.yahoo.vespaxmlparser.FeedOperation; /** * Keeps an operation with its message. * - * @author dybis + * @author Haakon Dybdahl */ class DocumentOperationMessageV3 { diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java index ccd0075a58a..4c98dba87cf 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedHandlerV3.java @@ -27,7 +27,7 @@ import java.util.logging.Logger; * One client has one ClientFeederV3 shared between all client threads. * Contains logic for shutting down cleanly as the server is upgraded. * - * @author dybis + * @author Haakon Dybdahl */ public class FeedHandlerV3 extends ThreadedHttpRequestHandler { diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedReaderFactory.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedReaderFactory.java index c501fbfc500..792115f2570 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedReaderFactory.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/FeedReaderFactory.java @@ -11,7 +11,7 @@ import java.io.InputStream; /** * Class for creating FeedReader based on dataFormat. - * @author dybis + * @author Haakon Dybdahl */ public class FeedReaderFactory { private static final int MARK_READLIMIT = 200; diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/StreamReaderV3.java b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/StreamReaderV3.java index bd1c66a36e5..1dd640004d3 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/StreamReaderV3.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/vespa/http/server/StreamReaderV3.java @@ -15,7 +15,7 @@ import java.util.zip.GZIPInputStream; /** * This code is based on v2 code, but restructured so stream reading code is in one dedicated class. * - * @author dybis + * @author Haakon Dybdahl */ public class StreamReaderV3 { diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/vespaxmlparser/MockFeedReaderFactory.java b/vespaclient-container-plugin/src/test/java/com/yahoo/vespaxmlparser/MockFeedReaderFactory.java index 9de368c24df..6d05af112ce 100644 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/vespaxmlparser/MockFeedReaderFactory.java +++ b/vespaclient-container-plugin/src/test/java/com/yahoo/vespaxmlparser/MockFeedReaderFactory.java @@ -9,7 +9,7 @@ import java.io.InputStream; /** * For creating MockReader of innput stream. - * @author dybis + * @author Haakon Dybdahl */ public class MockFeedReaderFactory extends FeedReaderFactory { diff --git a/vespalib/src/tests/btree/btree_test.cpp b/vespalib/src/tests/btree/btree_test.cpp index a43fbf01ad1..c8aa7feb123 100644 --- a/vespalib/src/tests/btree/btree_test.cpp +++ b/vespalib/src/tests/btree/btree_test.cpp @@ -1072,7 +1072,7 @@ adjustAllocatedBytes(size_t nodeCount, size_t nodeSize) TEST_F(BTreeTest, require_that_memory_usage_is_calculated) { constexpr size_t BASE_ALLOCATED = 28744u; - constexpr size_t BASE_USED = 24936; + constexpr size_t BASE_USED = 24920; typedef BTreeNodeAllocator<int32_t, int8_t, btree::NoAggregated, MyTraits::INTERNAL_SLOTS, MyTraits::LEAF_SLOTS> NodeAllocator; diff --git a/vespalib/src/tests/datastore/array_store/array_store_test.cpp b/vespalib/src/tests/datastore/array_store/array_store_test.cpp index dc248ec2fed..a65a73ad9bb 100644 --- a/vespalib/src/tests/datastore/array_store/array_store_test.cpp +++ b/vespalib/src/tests/datastore/array_store/array_store_test.cpp @@ -278,10 +278,10 @@ TYPED_TEST(NumberStoreTest, control_static_sizes) { MemoryUsage usage = this->store.getMemoryUsage(); if (this->simple_buffers()) { EXPECT_EQ(202140u, usage.allocatedBytes()); - EXPECT_EQ(197680u, usage.usedBytes()); + EXPECT_EQ(197648u, usage.usedBytes()); } else { EXPECT_EQ(202328u, usage.allocatedBytes()); - EXPECT_EQ(197568u, usage.usedBytes()); + EXPECT_EQ(197536u, usage.usedBytes()); } } diff --git a/vespalib/src/tests/datastore/datastore/datastore_test.cpp b/vespalib/src/tests/datastore/datastore/datastore_test.cpp index 540fb05a8a6..e0557226e3c 100644 --- a/vespalib/src/tests/datastore/datastore/datastore_test.cpp +++ b/vespalib/src/tests/datastore/datastore/datastore_test.cpp @@ -475,7 +475,7 @@ TEST(DataStoreTest, require_that_memory_stats_are_calculated) TEST(DataStoreTest, require_that_memory_usage_is_calculated) { constexpr size_t BASE_ALLOCATED = 4228; - constexpr size_t BASE_USED = 284; + constexpr size_t BASE_USED = 276; MyStore s; MyRef r = s.addEntry(10); s.addEntry(20); @@ -494,7 +494,7 @@ TEST(DataStoreTest, require_that_memory_usage_is_calculated) TEST(DataStoreTest, require_that_we_can_disable_elemement_hold_list) { constexpr size_t BASE_ALLOCATED = 4228; - constexpr size_t BASE_USED = 284; + constexpr size_t BASE_USED = 276; MyStore s; MyRef r1 = s.addEntry(10); MyRef r2 = s.addEntry(20); @@ -667,9 +667,9 @@ TEST(DataStoreTest, can_reuse_active_buffer_as_primary_buffer) TEST(DataStoreTest, control_static_sizes) { EXPECT_EQ(96, sizeof(BufferTypeBase)); EXPECT_EQ(24, sizeof(FreeList)); - EXPECT_EQ(48, sizeof(BufferFreeList)); + EXPECT_EQ(40, sizeof(BufferFreeList)); EXPECT_EQ(1, sizeof(BufferState::State)); - EXPECT_EQ(120, sizeof(BufferState)); + EXPECT_EQ(112, sizeof(BufferState)); BufferState bs; EXPECT_EQ(0, bs.size()); } diff --git a/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp b/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp index 2c359db59b1..4d271618250 100644 --- a/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp +++ b/vespalib/src/tests/datastore/unique_store/unique_store_test.cpp @@ -465,13 +465,13 @@ TEST_F(DoubleTest, nan_is_handled) TEST_F(DoubleTest, control_memory_usage) { static constexpr size_t sizeof_deque = vespalib::datastore::DataStoreBase::sizeof_entry_ref_hold_list_deque; EXPECT_EQ(400u + sizeof_deque, sizeof(store)); - EXPECT_EQ(120u, sizeof(BufferState)); + EXPECT_EQ(112u, sizeof(BufferState)); EXPECT_EQ(28740u, store.get_values_memory_usage().allocatedBytes()); - EXPECT_EQ(24780u, store.get_values_memory_usage().usedBytes()); + EXPECT_EQ(24772u, store.get_values_memory_usage().usedBytes()); EXPECT_EQ(126952u, store.get_dictionary_memory_usage().allocatedBytes()); - EXPECT_EQ(25200u, store.get_dictionary_memory_usage().usedBytes()); + EXPECT_EQ(25184u, store.get_dictionary_memory_usage().usedBytes()); EXPECT_EQ(155692u, store.getMemoryUsage().allocatedBytes()); - EXPECT_EQ(49980u, store.getMemoryUsage().usedBytes()); + EXPECT_EQ(49956u, store.getMemoryUsage().usedBytes()); } GTEST_MAIN_RUN_ALL_TESTS() diff --git a/vespalib/src/vespa/vespalib/btree/btreeiterator.h b/vespalib/src/vespa/vespalib/btree/btreeiterator.h index a0d189ef03c..505ad4c5c3b 100644 --- a/vespalib/src/vespa/vespalib/btree/btreeiterator.h +++ b/vespalib/src/vespa/vespalib/btree/btreeiterator.h @@ -39,7 +39,7 @@ class NodeElement using DataType = typename NodeType::DataType; uint64_t _nodeAndIdx; - NodeType * getWNode() const { return const_cast<NodeType *>(getNode()); } + NodeType * getWNode() const noexcept { return const_cast<NodeType *>(getNode()); } static constexpr uint8_t NODE_BITS = 57; static constexpr uint8_t IDX_BITS = 64 - NODE_BITS; static constexpr uint64_t NODE_MASK = (1ul << NODE_BITS) - 1ul; @@ -162,12 +162,12 @@ private: /* * Find the next leaf node, called by operator++() as needed. */ - void findNextLeafNode(); + void findNextLeafNode() noexcept; /* * Find the previous leaf node, called by operator--() as needed. */ - void findPrevLeafNode(); + void findPrevLeafNode() noexcept; protected: /* @@ -175,7 +175,7 @@ protected: * * @param pidx Number of levels above leaf nodes to take into account. */ - size_t position(uint32_t pidx) const; + size_t position(uint32_t pidx) const noexcept; /** * Create iterator pointing to first element in the tree referenced @@ -184,7 +184,7 @@ protected: * @param root Reference to root of tree * @param allocator B-tree node allocator helper class. */ - BTreeIteratorBase(BTreeNode::Ref root, const NodeAllocatorType &allocator); + BTreeIteratorBase(BTreeNode::Ref root, const NodeAllocatorType &allocator) noexcept; /** * Compability constructor, creating a temporary tree with only a @@ -204,7 +204,7 @@ protected: /** * Step iterator forwards. If at end then leave it at end. */ - BTreeIteratorBase & operator++() { + BTreeIteratorBase & operator++() noexcept { if (_leaf.getNode() == nullptr) { return *this; } @@ -220,7 +220,7 @@ protected: * Step iterator backwards. If at end then place it at last valid * position in tree (cf. rbegin()) */ - BTreeIteratorBase & operator--() { + BTreeIteratorBase & operator--() noexcept { if (_leaf.getNode() == nullptr) { rbegin(); return *this; @@ -233,17 +233,17 @@ protected: return *this; } - void set_subtree_position(const InternalNodeType* node, uint32_t level, uint32_t idx, size_t position); + void set_subtree_position(const InternalNodeType* node, uint32_t level, uint32_t idx, size_t position) noexcept; /* * Step iterator forwards the given number of steps. */ - void step_forward(size_t steps); + void step_forward(size_t steps) noexcept; /* * Step iterator backwards the given number of steps. */ - void step_backward(size_t steps); + void step_backward(size_t steps) noexcept; ~BTreeIteratorBase(); BTreeIteratorBase(const BTreeIteratorBase &other); @@ -256,7 +256,7 @@ protected: * * @param pathSize New tree height (number of levels of internal nodes) */ - void clearPath(uint32_t pathSize); + void clearPath(uint32_t pathSize) noexcept; /** * Call func with leaf entry key value as argument for all leaf entries in subtree @@ -347,12 +347,12 @@ public: /** * Return the current position in the tree. */ - size_t position() const { return position(_pathSize); } + size_t position() const noexcept { return position(_pathSize); } /** * Return the distance between two positions in the tree. */ - ssize_t operator-(const BTreeIteratorBase &rhs) const; + ssize_t operator-(const BTreeIteratorBase &rhs) const noexcept; /** * Return if the tree has data or not (e.g. keys and data or only keys). @@ -362,12 +362,14 @@ public: /** * Move the iterator directly to end. Used by findHelper method in BTree. */ - void setupEnd(); + void setupEnd() noexcept { + _leaf.invalidate(); + } /** * Setup iterator to be empty and not be associated with any tree. */ - void setupEmpty() { + void setupEmpty() noexcept { clearPath(0u); _leaf.invalidate(); _leafRoot = nullptr; @@ -376,44 +378,43 @@ public: /** * Move iterator to beyond last element in the current tree. */ - void end() __attribute__((noinline)); + void end() noexcept __attribute__((noinline)); /** * Move iterator to beyond last element in the given tree. * * @param rootRef Reference to root of tree. */ - void end(BTreeNode::Ref rootRef); + void end(BTreeNode::Ref rootRef) noexcept; /** * Move iterator to first element in the current tree. */ - void begin(); + void begin() noexcept; /** * Move iterator to first element in the given tree. * * @param rootRef Reference to root of tree. */ - void begin(BTreeNode::Ref rootRef); + void begin(BTreeNode::Ref rootRef) noexcept; /** * Move iterator to last element in the current tree. */ - void rbegin(); + void rbegin() noexcept; /* * Get aggregated values for the current tree. */ - const AggrT & getAggregated() const; + const AggrT & getAggregated() const noexcept; - bool identical(const BTreeIteratorBase &rhs) const; + bool identical(const BTreeIteratorBase &rhs) const noexcept; template <typename FunctionType> - void foreach_key(FunctionType func) const { + void foreach_key(FunctionType func) const noexcept { if (_pathSize > 0) { - _path[_pathSize - 1].getNode()-> - foreach_key(_allocator->getNodeStore(), func); + _path[_pathSize - 1].getNode()->foreach_key(_allocator->getNodeStore(), func); } else if (_leafRoot != nullptr) { _leafRoot->foreach_key(func); } @@ -425,7 +426,7 @@ public: * range [this iterator, end_itr)). */ template <typename FunctionType> - void foreach_key_range(const BTreeIteratorBase &end_itr, FunctionType func) const { + void foreach_key_range(const BTreeIteratorBase &end_itr, FunctionType func) const noexcept { if (!valid()) { return; } @@ -536,7 +537,7 @@ public: * @param root Reference to root of tree * @param allocator B-tree node allocator helper class. */ - BTreeConstIterator(BTreeNode::Ref root, const NodeAllocatorType &allocator) + BTreeConstIterator(BTreeNode::Ref root, const NodeAllocatorType &allocator) noexcept : ParentType(root, allocator) { } @@ -562,7 +563,7 @@ public: /** * Step iterator forwards. If at end then leave it at end. */ - BTreeConstIterator & operator++() { + BTreeConstIterator & operator++() noexcept { ParentType::operator++(); return *this; } @@ -571,7 +572,7 @@ public: * Step iterator backwards. If at end then place it at last valid * position in tree (cf. rbegin()) */ - BTreeConstIterator & operator--() { + BTreeConstIterator & operator--() noexcept { ParentType::operator--(); return *this; } @@ -579,7 +580,7 @@ public: /* * Step iterator forwards the given number of steps. */ - BTreeConstIterator & operator+=(size_t steps) { + BTreeConstIterator & operator+=(size_t steps) noexcept { step_forward(steps); return *this; } @@ -587,7 +588,7 @@ public: /* * Step iterator backward the given number of steps. */ - BTreeConstIterator & operator-=(size_t steps) { + BTreeConstIterator & operator-=(size_t steps) noexcept { step_backward(steps); return *this; } @@ -599,7 +600,7 @@ public: * @param key Key to search for * @param comp Comparator for the tree ordering. */ - void lower_bound(const KeyType & key, CompareT comp = CompareT()); + void lower_bound(const KeyType & key, CompareT comp = CompareT()) noexcept; /** * Position iterator at first position with a key that is greater @@ -608,7 +609,7 @@ public: * @param key Key to search for * @param comp Comparator for the tree ordering. */ - void lower_bound(BTreeNode::Ref rootRef, const KeyType & key, CompareT comp = CompareT()); + void lower_bound(BTreeNode::Ref rootRef, const KeyType & key, CompareT comp = CompareT()) noexcept; /** * Step iterator forwards until it is at a position with a key @@ -621,7 +622,7 @@ public: * @param key Key to search for * @param comp Comparator for the tree ordering. */ - void seek(const KeyType &key, CompareT comp = CompareT()); + void seek(const KeyType &key, CompareT comp = CompareT()) noexcept; /** * Step iterator forwards until it is at a position with a key @@ -633,7 +634,7 @@ public: * @param key Key to search for * @param comp Comparator for the tree ordering. */ - void binarySeek(const KeyType &key, CompareT comp = CompareT()); + void binarySeek(const KeyType &key, CompareT comp = CompareT()) noexcept; /** * Step iterator forwards until it is at a position with a key @@ -645,7 +646,7 @@ public: * @param key Key to search for * @param comp Comparator for the tree ordering. */ - void linearSeek(const KeyType &key, CompareT comp = CompareT()); + void linearSeek(const KeyType &key, CompareT comp = CompareT()) noexcept; /** * Step iterator forwards until it is at a position with a key @@ -658,7 +659,7 @@ public: * @param key Key to search for * @param comp Comparator for the tree ordering. */ - void seekPast(const KeyType &key, CompareT comp = CompareT()); + void seekPast(const KeyType &key, CompareT comp = CompareT()) noexcept; /** * Step iterator forwards until it is at a position with a key @@ -670,7 +671,7 @@ public: * @param key Key to search for * @param comp Comparator for the tree ordering. */ - void binarySeekPast(const KeyType &key, CompareT comp = CompareT()); + void binarySeekPast(const KeyType &key, CompareT comp = CompareT()) noexcept; /** * Step iterator forwards until it is at a position with a key @@ -682,7 +683,7 @@ public: * @param key Key to search for * @param comp Comparator for the tree ordering. */ - void linearSeekPast(const KeyType &key, CompareT comp = CompareT()); + void linearSeekPast(const KeyType &key, CompareT comp = CompareT()) noexcept; /** * Validate the iterator as a valid iterator or positioned at @@ -692,7 +693,7 @@ public: * @param rootRef Reference to root of tree to operate on * @param comp Comparator for the tree ordering. */ - void validate(BTreeNode::Ref rootRef, CompareT comp = CompareT()); + void validate(BTreeNode::Ref rootRef, CompareT comp = CompareT()) noexcept; }; @@ -737,7 +738,7 @@ public: using ParentType::step_forward; using EntryRef = datastore::EntryRef; - BTreeIterator(BTreeNode::Ref root, const NodeAllocatorType &allocator) + BTreeIterator(BTreeNode::Ref root, const NodeAllocatorType &allocator) noexcept : ParentType(root, allocator) { } @@ -751,29 +752,29 @@ public: { } - BTreeIterator() : ParentType() { } + BTreeIterator() noexcept : ParentType() { } - BTreeIterator & operator++() { + BTreeIterator & operator++() noexcept { ParentType::operator++(); return *this; } - BTreeIterator & operator--() { + BTreeIterator & operator--() noexcept { ParentType::operator--(); return *this; } - BTreeIterator & operator+=(size_t steps) { + BTreeIterator & operator+=(size_t steps) noexcept { step_forward(steps); return *this; } - BTreeIterator & operator-=(size_t steps) { + BTreeIterator & operator-=(size_t steps) noexcept { step_backward(steps); return *this; } - NodeAllocatorType & getAllocator() const { + NodeAllocatorType & getAllocator() const noexcept { return const_cast<NodeAllocatorType &>(*_allocator); } @@ -781,19 +782,19 @@ public: void moveNextLeafNode(); - void writeData(const DataType &data) { + void writeData(const DataType &data) noexcept { _leaf.getWNode()->writeData(_leaf.getIdx(), data); } // Only use during compaction when changing reference to moved value - DataType &getWData() { return _leaf.getWData(); } + DataType &getWData() noexcept { return _leaf.getWData(); } /** * Set a new key for the current iterator position. * The new key must have the same semantic meaning as the old key. * Typically used when compacting data store containing keys. */ - void writeKey(const KeyType &key); + void writeKey(const KeyType &key) noexcept; /** * Updata data at the current iterator position. The tree should @@ -803,7 +804,7 @@ public: * @param aggrCalc Calculator for updating aggregated information. */ template <class AggrCalcT> - void updateData(const DataType &data, const AggrCalcT &aggrCalc); + void updateData(const DataType &data, const AggrCalcT &aggrCalc) noexcept; /** * Thaw a path from the root node down the the current leaf node in @@ -816,12 +817,12 @@ private: /* Insert into empty tree */ template <class AggrCalcT> BTreeNode::Ref insertFirst(const KeyType &key, const DataType &data, const AggrCalcT &aggrCalc); - LeafNodeType * getLeafNode() const { return _leaf.getWNode(); } - bool setLeafNodeIdx(uint32_t idx, const LeafNodeType *splitLeafNode); - void setLeafNodeIdx(uint32_t idx) { _leaf.setIdx(idx); } - uint32_t getLeafNodeIdx() const { return _leaf.getIdx(); } - uint32_t getPathSize() const { return _pathSize; } - PathElement & getPath(uint32_t pidx) { return _path[pidx]; } + LeafNodeType * getLeafNode() const noexcept { return _leaf.getWNode(); } + bool setLeafNodeIdx(uint32_t idx, const LeafNodeType *splitLeafNode) noexcept; + void setLeafNodeIdx(uint32_t idx) noexcept { _leaf.setIdx(idx); } + uint32_t getLeafNodeIdx() const noexcept { return _leaf.getIdx(); } + uint32_t getPathSize() const noexcept { return _pathSize; } + PathElement & getPath(uint32_t pidx) noexcept { return _path[pidx]; } template <class AggrCalcT> BTreeNode::Ref addLevel(BTreeNode::Ref rootRef, BTreeNode::Ref splitNodeRef, bool inRightSplit, const AggrCalcT &aggrCalc); diff --git a/vespalib/src/vespa/vespalib/btree/btreeiterator.hpp b/vespalib/src/vespa/vespalib/btree/btreeiterator.hpp index bdca5e2c4ff..e1196d7c6db 100644 --- a/vespalib/src/vespa/vespalib/btree/btreeiterator.hpp +++ b/vespalib/src/vespa/vespalib/btree/btreeiterator.hpp @@ -52,7 +52,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -clearPath(uint32_t pathSize) +clearPath(uint32_t pathSize) noexcept { uint32_t level = _pathSize; while (level > pathSize) { @@ -84,18 +84,7 @@ BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>::~B template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void -BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -setupEnd() -{ - _leaf.invalidate(); -} - - -template <typename KeyT, typename DataT, typename AggrT, - uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> -void -BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -end() +BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>::end() noexcept { if (_pathSize == 0) { if (_leafRoot == nullptr) @@ -126,8 +115,7 @@ end() template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void -BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -end(BTreeNode::Ref rootRef) +BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>::end(BTreeNode::Ref rootRef) noexcept { if (!rootRef.valid()) { setupEmpty(); @@ -167,7 +155,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -findNextLeafNode() +findNextLeafNode() noexcept { uint32_t pidx; for (pidx = 0; pidx < _pathSize; ++pidx) { @@ -195,7 +183,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -findPrevLeafNode() +findPrevLeafNode() noexcept { uint32_t pidx; for (pidx = 0; pidx < _pathSize; ++pidx) { @@ -225,8 +213,7 @@ findPrevLeafNode() template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void -BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -begin() +BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>::begin() noexcept { uint32_t pidx = _pathSize; if (pidx > 0u) { @@ -251,8 +238,7 @@ begin() template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void -BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -begin(BTreeNode::Ref rootRef) +BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>::begin(BTreeNode::Ref rootRef) noexcept { if (!rootRef.valid()) { setupEmpty(); @@ -288,8 +274,7 @@ begin(BTreeNode::Ref rootRef) template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void -BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -rbegin() +BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>::rbegin() noexcept { uint32_t pidx = _pathSize; if (pidx > 0u) { @@ -310,10 +295,7 @@ rbegin() const LeafNodeType *lnode(_allocator->mapLeafRef(node)); _leaf.setNodeAndIdx(lnode, lnode->validSlots() - 1); } else { - _leaf.setNodeAndIdx(_leafRoot, - (_leafRoot != nullptr) ? - _leafRoot->validSlots() - 1 : - 0u); + _leaf.setNodeAndIdx(_leafRoot, (_leafRoot != nullptr) ? _leafRoot->validSlots() - 1 : 0u); } } @@ -322,7 +304,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> const AggrT & BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -getAggregated() const +getAggregated() const noexcept { // XXX: Undefined behavior if tree is empty. uint32_t pidx = _pathSize; @@ -340,7 +322,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> size_t BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -position(uint32_t levels) const +position(uint32_t levels) const noexcept { assert(_pathSize >= levels); if (_leaf.getNode() == nullptr) @@ -393,8 +375,7 @@ position(uint32_t levels) const template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -BTreeIteratorBase(BTreeNode::Ref root, - const NodeAllocatorType &allocator) +BTreeIteratorBase(BTreeNode::Ref root, const NodeAllocatorType &allocator) noexcept : _leaf(nullptr, 0u), _path(), _pathSize(0), @@ -467,7 +448,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> ssize_t BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -operator-(const BTreeIteratorBase &rhs) const +operator-(const BTreeIteratorBase &rhs) const noexcept { if (_leaf.getNode() == nullptr) { if (rhs._leaf.getNode() == nullptr) @@ -497,7 +478,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> bool BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -identical(const BTreeIteratorBase &rhs) const +identical(const BTreeIteratorBase &rhs) const noexcept { if (_pathSize != rhs._pathSize || _leaf != rhs._leaf) { HDR_ABORT("should not be reached"); @@ -518,7 +499,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -set_subtree_position(const InternalNodeType* node, uint32_t level, uint32_t idx, size_t position) +set_subtree_position(const InternalNodeType* node, uint32_t level, uint32_t idx, size_t position) noexcept { /* * Walk down subtree adjusting iterator for new partial position. @@ -550,7 +531,7 @@ template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -step_forward(size_t steps) +step_forward(size_t steps) noexcept { auto lnode = _leaf.getNode(); if (lnode == nullptr) { @@ -600,8 +581,7 @@ step_forward(size_t steps) template <typename KeyT, typename DataT, typename AggrT, uint32_t INTERNAL_SLOTS, uint32_t LEAF_SLOTS, uint32_t PATH_SIZE> void -BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>:: -step_backward(size_t steps) +BTreeIteratorBase<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS, PATH_SIZE>::step_backward(size_t steps) noexcept { int64_t remaining_steps = steps; if (remaining_steps == 0) { @@ -651,11 +631,10 @@ step_backward(size_t steps) set_subtree_position(node, level, idx, -remaining_steps); } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -lower_bound(const KeyType & key, CompareT comp) +lower_bound(const KeyType & key, CompareT comp) noexcept { if (_pathSize == 0) { if (_leafRoot == nullptr) @@ -696,11 +675,10 @@ lower_bound(const KeyType & key, CompareT comp) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -lower_bound(BTreeNode::Ref rootRef, const KeyType & key, CompareT comp) +lower_bound(BTreeNode::Ref rootRef, const KeyType & key, CompareT comp) noexcept { if (!rootRef.valid()) { setupEmpty(); @@ -748,11 +726,10 @@ lower_bound(BTreeNode::Ref rootRef, const KeyType & key, CompareT comp) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -seek(const KeyType & key, CompareT comp) +seek(const KeyType & key, CompareT comp) noexcept { if (TraitsT::BINARY_SEEK) { binarySeek(key, comp); @@ -761,11 +738,10 @@ seek(const KeyType & key, CompareT comp) } } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -binarySeek(const KeyType & key, CompareT comp) +binarySeek(const KeyType & key, CompareT comp) noexcept { const LeafNodeType *lnode = _leaf.getNode(); uint32_t lidx = _leaf.getIdx() + 1; @@ -806,11 +782,10 @@ binarySeek(const KeyType & key, CompareT comp) _leaf.setIdx(lidx); } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -linearSeek(const KeyType & key, CompareT comp) +linearSeek(const KeyType & key, CompareT comp) noexcept { const LeafNodeType *lnode = _leaf.getNode(); uint32_t lidx = _leaf.getIdx() + 1; @@ -858,11 +833,10 @@ linearSeek(const KeyType & key, CompareT comp) _leaf.setIdx(lidx); } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -seekPast(const KeyType & key, CompareT comp) +seekPast(const KeyType & key, CompareT comp) noexcept { if (TraitsT::BINARY_SEEK) { binarySeekPast(key, comp); @@ -871,11 +845,10 @@ seekPast(const KeyType & key, CompareT comp) } } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -binarySeekPast(const KeyType & key, CompareT comp) +binarySeekPast(const KeyType & key, CompareT comp) noexcept { const LeafNodeType *lnode = _leaf.getNode(); uint32_t lidx = _leaf.getIdx() + 1; @@ -916,11 +889,10 @@ binarySeekPast(const KeyType & key, CompareT comp) _leaf.setIdx(lidx); } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -linearSeekPast(const KeyType & key, CompareT comp) +linearSeekPast(const KeyType & key, CompareT comp) noexcept { const LeafNodeType *lnode = _leaf.getNode(); uint32_t lidx = _leaf.getIdx() + 1; @@ -970,11 +942,10 @@ linearSeekPast(const KeyType & key, CompareT comp) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeConstIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -validate(BTreeNode::Ref rootRef, CompareT comp) +validate(BTreeNode::Ref rootRef, CompareT comp) noexcept { bool frozen = false; if (!rootRef.valid()) { @@ -1036,8 +1007,7 @@ validate(BTreeNode::Ref rootRef, CompareT comp) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> BTreeNode::Ref BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: moveFirstLeafNode(BTreeNode::Ref rootRef) @@ -1100,11 +1070,9 @@ moveFirstLeafNode(BTreeNode::Ref rootRef) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void -BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -moveNextLeafNode() +BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>::moveNextLeafNode() { uint32_t level = 0; uint32_t levels = _pathSize; @@ -1146,11 +1114,9 @@ moveNextLeafNode() } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void -BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -writeKey(const KeyType & key) +BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>::writeKey(const KeyType & key) noexcept { LeafNodeType * lnode = getLeafNode(); lnode->writeKey(_leaf.getIdx(), key); @@ -1170,12 +1136,11 @@ writeKey(const KeyType & key) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> template <class AggrCalcT> void BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -updateData(const DataType & data, [[maybe_unused]] const AggrCalcT &aggrCalc) +updateData(const DataType & data, [[maybe_unused]] const AggrCalcT &aggrCalc) noexcept { LeafNodeType * lnode = getLeafNode(); if constexpr (AggrCalcT::hasAggregated() && AggrCalcT::aggregate_over_values()) { @@ -1198,8 +1163,7 @@ updateData(const DataType & data, [[maybe_unused]] const AggrCalcT &aggrCalc) const PathElement & pe = _path[i]; InternalNodeType * inode = pe.getWNode(); AggrT oldpa(inode->getAggregated()); - if (aggrCalc.update(inode->getAggregated(), - oldca, ca)) { + if (aggrCalc.update(inode->getAggregated(), oldca, ca)) { Aggregator::recalc(*inode, *_allocator, aggrCalc); } AggrT pa(inode->getAggregated()); @@ -1212,11 +1176,9 @@ updateData(const DataType & data, [[maybe_unused]] const AggrCalcT &aggrCalc) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> BTreeNode::Ref -BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -thaw(BTreeNode::Ref rootRef) +BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>::thaw(BTreeNode::Ref rootRef) { assert(_leaf.getNode() != nullptr && _compatLeafNode.get() == nullptr); if (!_leaf.getNode()->getFrozen()) @@ -1226,20 +1188,17 @@ thaw(BTreeNode::Ref rootRef) LeafNodeType *leafNode = allocator.mapLeafRef(rootRef); assert(leafNode == _leaf.getNode()); assert(leafNode == _leafRoot); - LeafNodeTypeRefPair thawedLeaf = allocator.thawNode(rootRef, - leafNode); + LeafNodeTypeRefPair thawedLeaf = allocator.thawNode(rootRef, leafNode); _leaf.setNode(thawedLeaf.data); _leafRoot = thawedLeaf.data; return thawedLeaf.ref; } assert(_leafRoot == nullptr); - assert(_path[_pathSize - 1].getNode() == - allocator.mapInternalRef(rootRef)); + assert(_path[_pathSize - 1].getNode() == allocator.mapInternalRef(rootRef)); BTreeNode::Ref childRef(_path[0].getNode()->getChild(_path[0].getIdx())); LeafNodeType *leafNode = allocator.mapLeafRef(childRef); assert(leafNode == _leaf.getNode()); - LeafNodeTypeRefPair thawedLeaf = allocator.thawNode(childRef, - leafNode); + LeafNodeTypeRefPair thawedLeaf = allocator.thawNode(childRef, leafNode); _leaf.setNode(thawedLeaf.data); childRef = thawedLeaf.ref; uint32_t level = 0; @@ -1247,10 +1206,9 @@ thaw(BTreeNode::Ref rootRef) while (level < levels) { PathElement &pe = _path[level]; InternalNodeType *node(pe.getWNode()); - BTreeNode::Ref nodeRef = level + 1 < levels ? - _path[level + 1].getNode()-> - getChild(_path[level + 1].getIdx()) : - rootRef; + BTreeNode::Ref nodeRef = (level + 1 < levels) + ? _path[level + 1].getNode()->getChild(_path[level + 1].getIdx()) + : rootRef; assert(node == allocator.mapInternalRef(nodeRef)); if (!node->getFrozen()) { node->set_child_relaxed(pe.getIdx(), childRef); @@ -1267,8 +1225,7 @@ thaw(BTreeNode::Ref rootRef) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> template <class AggrCalcT> BTreeNode::Ref BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: @@ -1295,16 +1252,14 @@ insertFirst(const KeyType &key, const DataType &data, } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> bool BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: -setLeafNodeIdx(uint32_t idx, const LeafNodeType *splitLeafNode) +setLeafNodeIdx(uint32_t idx, const LeafNodeType *splitLeafNode) noexcept { uint32_t leafSlots = _leaf.getNode()->validSlots(); if (idx >= leafSlots) { - _leaf.setNodeAndIdx(splitLeafNode, - idx - leafSlots); + _leaf.setNodeAndIdx(splitLeafNode, idx - leafSlots); if (_pathSize == 0) { _leafRoot = splitLeafNode; } @@ -1316,8 +1271,7 @@ setLeafNodeIdx(uint32_t idx, const LeafNodeType *splitLeafNode) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> template <class AggrCalcT> BTreeNode::Ref BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: @@ -1349,8 +1303,7 @@ addLevel(BTreeNode::Ref rootRef, BTreeNode::Ref splitNodeRef, } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> BTreeNode::Ref BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: removeLevel(BTreeNode::Ref rootRef, InternalNodeType *rootNode) @@ -1367,8 +1320,7 @@ removeLevel(BTreeNode::Ref rootRef, InternalNodeType *rootNode) } -template <typename KeyT, typename DataT, typename AggrT, typename CompareT, - typename TraitsT> +template <typename KeyT, typename DataT, typename AggrT, typename CompareT, typename TraitsT> void BTreeIterator<KeyT, DataT, AggrT, CompareT, TraitsT>:: removeLast(BTreeNode::Ref rootRef) diff --git a/vespalib/src/vespa/vespalib/btree/btreenode.h b/vespalib/src/vespa/vespalib/btree/btreenode.h index c4862a256c9..d7741393d0e 100644 --- a/vespalib/src/vespa/vespalib/btree/btreenode.h +++ b/vespalib/src/vespa/vespalib/btree/btreenode.h @@ -92,7 +92,7 @@ public: BTreeNodeDataWrap() noexcept : _data() {} ~BTreeNodeDataWrap() = default; - void copyData(const BTreeNodeDataWrap &rhs, uint32_t validSlots) { + void copyData(const BTreeNodeDataWrap &rhs, uint32_t validSlots) noexcept { const DataT *rdata = rhs._data; DataT *ldata = _data; DataT *ldatae = _data + validSlots; @@ -112,27 +112,27 @@ template <uint32_t NumSlots> class BTreeNodeDataWrap<BTreeNoLeafData, NumSlots> { public: - BTreeNodeDataWrap() noexcept {} + BTreeNodeDataWrap() noexcept = default; - void copyData(const BTreeNodeDataWrap &rhs, uint32_t validSlots) { + void copyData(const BTreeNodeDataWrap &rhs, uint32_t validSlots) noexcept { (void) rhs; (void) validSlots; } - const BTreeNoLeafData &getData(uint32_t idx) const { + const BTreeNoLeafData &getData(uint32_t idx) const noexcept { (void) idx; return BTreeNoLeafData::_instance; } // Only use during compaction when changing reference to moved value - BTreeNoLeafData &getWData(uint32_t) const { return BTreeNoLeafData::_instance; } + BTreeNoLeafData &getWData(uint32_t) const noexcept { return BTreeNoLeafData::_instance; } - void setData(uint32_t idx, const BTreeNoLeafData &data) { + void setData(uint32_t idx, const BTreeNoLeafData &data) noexcept { (void) idx; (void) data; } - static bool hasData() { return false; } + static constexpr bool hasData() noexcept { return false; } }; @@ -148,9 +148,9 @@ public: BTreeNodeAggregatedWrap() noexcept : _aggr() {} - AggrT &getAggregated() { return _aggr; } - const AggrT &getAggregated() const { return _aggr; } - static const AggrT &getEmptyAggregated() { return _instance; } + AggrT &getAggregated() noexcept { return _aggr; } + const AggrT &getAggregated() const noexcept { return _aggr; } + static const AggrT &getEmptyAggregated() noexcept { return _instance; } }; @@ -163,9 +163,9 @@ class BTreeNodeAggregatedWrap<NoAggregated> public: BTreeNodeAggregatedWrap() noexcept = default; - NoAggregated &getAggregated() { return _instance; } - const NoAggregated &getAggregated() const { return _instance; } - static const NoAggregated &getEmptyAggregated() { return _instance; } + NoAggregated &getAggregated() noexcept { return _instance; } + const NoAggregated &getAggregated() const noexcept { return _instance; } + static const NoAggregated &getEmptyAggregated() noexcept { return _instance; } }; template <> MinMaxAggregated BTreeNodeAggregatedWrap<MinMaxAggregated>::_instance; @@ -216,13 +216,13 @@ public: void write_key_relaxed(uint32_t idx, const KeyT & key) noexcept { _keys[idx] = key; } template <typename CompareT> - uint32_t lower_bound(uint32_t sidx, const KeyT & key, CompareT comp) const; + uint32_t lower_bound(uint32_t sidx, const KeyT & key, CompareT comp) const noexcept; template <typename CompareT> - uint32_t lower_bound(const KeyT & key, CompareT comp) const; + uint32_t lower_bound(const KeyT & key, CompareT comp) const noexcept; template <typename CompareT> - uint32_t upper_bound(uint32_t sidx, const KeyT & key, CompareT comp) const; + uint32_t upper_bound(uint32_t sidx, const KeyT & key, CompareT comp) const noexcept; bool isFull() const noexcept { return validSlots() == NumSlots; } bool isAtLeastHalfFull() const noexcept { return validSlots() >= minSlots(); } @@ -271,22 +271,22 @@ protected: public: using NodeType = BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>; - void insert(uint32_t idx, const KeyT & key, const DataT & data); - void update(uint32_t idx, const KeyT & key, const DataT & data) { + void insert(uint32_t idx, const KeyT & key, const DataT & data) noexcept; + void update(uint32_t idx, const KeyT & key, const DataT & data) noexcept { // assert(idx < NodeType::maxSlots()); // assert(!getFrozen()); _keys[idx] = key; setData(idx, data); } - void splitInsert(NodeType * splitNode, uint32_t idx, const KeyT & key, const DataT & data); - void remove(uint32_t idx); - void stealAllFromLeftNode(const NodeType * victim); - void stealAllFromRightNode(const NodeType * victim); - void stealSomeFromLeftNode(NodeType * victim); - void stealSomeFromRightNode(NodeType * victim); - void cleanRange(uint32_t from, uint32_t to); - void clean(); - void cleanFrozen(); + void splitInsert(NodeType * splitNode, uint32_t idx, const KeyT & key, const DataT & data) noexcept; + void remove(uint32_t idx) noexcept; + void stealAllFromLeftNode(const NodeType * victim) noexcept; + void stealAllFromRightNode(const NodeType * victim) noexcept; + void stealSomeFromLeftNode(NodeType * victim) noexcept; + void stealSomeFromRightNode(NodeType * victim) noexcept; + void cleanRange(uint32_t from, uint32_t to) noexcept; + void clean() noexcept; + void cleanFrozen() noexcept; }; template <typename KeyT, typename AggrT, uint32_t NumSlots = 16> @@ -344,53 +344,53 @@ protected: } private: template <typename NodeAllocatorType> - uint32_t countValidLeaves(uint32_t start, uint32_t end, NodeAllocatorType &allocator); + uint32_t countValidLeaves(uint32_t start, uint32_t end, NodeAllocatorType &allocator) noexcept; public: - BTreeNode::Ref getChild(uint32_t idx) const { return _data[idx].load_acquire(); } - BTreeNode::Ref get_child_relaxed(uint32_t idx) const { return _data[idx].load_relaxed(); } - void setChild(uint32_t idx, BTreeNode::Ref child) { _data[idx].store_release(child); } - void set_child_relaxed(uint32_t idx, BTreeNode::Ref child) { _data[idx].store_relaxed(child); } - BTreeNode::Ref get_last_child_relaxed() const { return get_child_relaxed(validSlots() - 1); } - void update(uint32_t idx, const KeyT & key, BTreeNode::Ref child) { + BTreeNode::Ref getChild(uint32_t idx) const noexcept { return _data[idx].load_acquire(); } + BTreeNode::Ref get_child_relaxed(uint32_t idx) const noexcept { return _data[idx].load_relaxed(); } + void setChild(uint32_t idx, BTreeNode::Ref child) noexcept { _data[idx].store_release(child); } + void set_child_relaxed(uint32_t idx, BTreeNode::Ref child) noexcept { _data[idx].store_relaxed(child); } + BTreeNode::Ref get_last_child_relaxed() const noexcept { return get_child_relaxed(validSlots() - 1); } + void update(uint32_t idx, const KeyT & key, BTreeNode::Ref child) noexcept { update(idx, key, BTreeNode::ChildRef(child)); } - void insert(uint32_t idx, const KeyT & key, BTreeNode::Ref child) { + void insert(uint32_t idx, const KeyT & key, BTreeNode::Ref child) noexcept { insert(idx, key, BTreeNode::ChildRef(child)); } uint32_t validLeaves() const noexcept { return _validLeaves; } - void setValidLeaves(uint32_t newValidLeaves) { _validLeaves = newValidLeaves; } - void incValidLeaves(uint32_t delta) { _validLeaves += delta; } - void decValidLeaves(uint32_t delta) { _validLeaves -= delta; } + void setValidLeaves(uint32_t newValidLeaves) noexcept { _validLeaves = newValidLeaves; } + void incValidLeaves(uint32_t delta) noexcept { _validLeaves += delta; } + void decValidLeaves(uint32_t delta) noexcept { _validLeaves -= delta; } template <typename NodeAllocatorType> void splitInsert(BTreeInternalNode *splitNode, uint32_t idx, const KeyT &key, - const BTreeNode::Ref &data, NodeAllocatorType &allocator); + const BTreeNode::Ref &data, NodeAllocatorType &allocator) noexcept; - void stealAllFromLeftNode(const BTreeInternalNode *victim); - void stealAllFromRightNode(const BTreeInternalNode *victim); + void stealAllFromLeftNode(const BTreeInternalNode *victim) noexcept; + void stealAllFromRightNode(const BTreeInternalNode *victim) noexcept; template <typename NodeAllocatorType> - void stealSomeFromLeftNode(BTreeInternalNode *victim, NodeAllocatorType &allocator); + void stealSomeFromLeftNode(BTreeInternalNode *victim, NodeAllocatorType &allocator) noexcept; template <typename NodeAllocatorType> - void stealSomeFromRightNode(BTreeInternalNode *victim, NodeAllocatorType &allocator); + void stealSomeFromRightNode(BTreeInternalNode *victim, NodeAllocatorType &allocator) noexcept; - void clean(); - void cleanFrozen(); + void clean() noexcept; + void cleanFrozen() noexcept; template <typename NodeStoreType, typename FunctionType> - void foreach_key(NodeStoreType &store, FunctionType func) const; + void foreach_key(NodeStoreType &store, FunctionType func) const noexcept; /** * Call func with leaf entry key value as argument for all leaf entries in subtrees * for children [start_idx, end_idx). */ template <typename NodeStoreType, typename FunctionType> - void foreach_key_range(NodeStoreType &store, uint32_t start_idx, uint32_t end_idx, FunctionType func) const; + void foreach_key_range(NodeStoreType &store, uint32_t start_idx, uint32_t end_idx, FunctionType func) const noexcept; template <typename NodeStoreType, typename FunctionType> - void foreach(NodeStoreType &store, FunctionType func) const; + void foreach(NodeStoreType &store, FunctionType func) const noexcept; }; template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots = 16> @@ -439,33 +439,31 @@ protected: public: template <typename NodeAllocatorType> - void stealSomeFromLeftNode(BTreeLeafNode *victim, NodeAllocatorType &allocator) + void stealSomeFromLeftNode(BTreeLeafNode *victim, NodeAllocatorType &) noexcept { - (void) allocator; stealSomeFromLeftNode(victim); } template <typename NodeAllocatorType> - void stealSomeFromRightNode(BTreeLeafNode *victim, NodeAllocatorType &allocator) { - (void) allocator; + void stealSomeFromRightNode(BTreeLeafNode *victim, NodeAllocatorType &) noexcept { stealSomeFromRightNode(victim); } - const DataT &getLastData() const { return this->getData(validSlots() - 1); } - void writeData(uint32_t idx, const DataT &data) { this->setData(idx, data); } + const DataT &getLastData() const noexcept { return this->getData(validSlots() - 1); } + void writeData(uint32_t idx, const DataT &data) noexcept { this->setData(idx, data); } uint32_t validLeaves() const noexcept { return validSlots(); } template <typename FunctionType> - void foreach_key(FunctionType func) const; + void foreach_key(FunctionType func) const noexcept; /** * Call func with leaf entry key value as argument for leaf entries [start_idx, end_idx). */ template <typename FunctionType> - void foreach_key_range(uint32_t start_idx, uint32_t end_idx, FunctionType func) const; + void foreach_key_range(uint32_t start_idx, uint32_t end_idx, FunctionType func) const noexcept; template <typename FunctionType> - void foreach(FunctionType func) const; + void foreach(FunctionType func) const noexcept; }; @@ -480,7 +478,7 @@ public: : ParentType(smallArray, arraySize) {} - ~BTreeLeafNodeTemp() {} + ~BTreeLeafNodeTemp() = default; }; extern template class BTreeNodeDataWrap<uint32_t, 16>; diff --git a/vespalib/src/vespa/vespalib/btree/btreenode.hpp b/vespalib/src/vespa/vespalib/btree/btreenode.hpp index 12b5c985ca6..c636851b4b2 100644 --- a/vespalib/src/vespa/vespalib/btree/btreenode.hpp +++ b/vespalib/src/vespa/vespalib/btree/btreenode.hpp @@ -42,7 +42,7 @@ template <typename KeyT, uint32_t NumSlots> template <typename CompareT> uint32_t BTreeNodeT<KeyT, NumSlots>:: -lower_bound(uint32_t sidx, const KeyT & key, CompareT comp) const +lower_bound(uint32_t sidx, const KeyT & key, CompareT comp) const noexcept { const KeyT * itr = std::lower_bound<const KeyT *, KeyT, CompareT> (_keys + sidx, _keys + validSlots(), key, comp); @@ -52,9 +52,8 @@ lower_bound(uint32_t sidx, const KeyT & key, CompareT comp) const template <typename KeyT, uint32_t NumSlots> template <typename CompareT> uint32_t -BTreeNodeT<KeyT, NumSlots>::lower_bound(const KeyT & key, CompareT comp) const +BTreeNodeT<KeyT, NumSlots>::lower_bound(const KeyT & key, CompareT comp) const noexcept { - const KeyT * itr = std::lower_bound<const KeyT *, KeyT, CompareT> (_keys, _keys + validSlots(), key, comp); return itr - _keys; @@ -65,7 +64,7 @@ template <typename KeyT, uint32_t NumSlots> template <typename CompareT> uint32_t BTreeNodeT<KeyT, NumSlots>:: -upper_bound(uint32_t sidx, const KeyT & key, CompareT comp) const +upper_bound(uint32_t sidx, const KeyT & key, CompareT comp) const noexcept { const KeyT * itr = std::upper_bound<const KeyT *, KeyT, CompareT> (_keys + sidx, _keys + validSlots(), key, comp); @@ -75,7 +74,7 @@ upper_bound(uint32_t sidx, const KeyT & key, CompareT comp) const template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void -BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::insert(uint32_t idx, const KeyT &key, const DataT &data) +BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::insert(uint32_t idx, const KeyT &key, const DataT &data) noexcept { assert(validSlots() < NodeType::maxSlots()); assert(!getFrozen()); @@ -90,10 +89,8 @@ BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::insert(uint32_t idx, const KeyT &key, template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void -BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::splitInsert(NodeType *splitNode, - uint32_t idx, - const KeyT &key, - const DataT &data) +BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>:: +splitInsert(NodeType *splitNode, uint32_t idx, const KeyT &key, const DataT &data) noexcept { assert(!getFrozen()); assert(!splitNode->getFrozen()); @@ -114,7 +111,7 @@ BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::splitInsert(NodeType *splitNode, template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void -BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::remove(uint32_t idx) +BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::remove(uint32_t idx) noexcept { assert(!getFrozen()); for (uint32_t i = idx + 1; i < validSlots(); ++i) { @@ -129,7 +126,7 @@ BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::remove(uint32_t idx) template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>:: -stealAllFromLeftNode(const NodeType *victim) +stealAllFromLeftNode(const NodeType *victim) noexcept { assert(validSlots() + victim->validSlots() <= NodeType::maxSlots()); assert(!getFrozen()); @@ -147,7 +144,7 @@ stealAllFromLeftNode(const NodeType *victim) template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>:: -stealAllFromRightNode(const NodeType *victim) +stealAllFromRightNode(const NodeType *victim) noexcept { assert(validSlots() + victim->validSlots() <= NodeType::maxSlots()); assert(!getFrozen()); @@ -161,7 +158,7 @@ stealAllFromRightNode(const NodeType *victim) template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>:: -stealSomeFromLeftNode(NodeType *victim) +stealSomeFromLeftNode(NodeType *victim) noexcept { assert(validSlots() + victim->validSlots() >= NodeType::minSlots()); assert(!getFrozen()); @@ -184,7 +181,7 @@ stealSomeFromLeftNode(NodeType *victim) template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>:: -stealSomeFromRightNode(NodeType *victim) +stealSomeFromRightNode(NodeType *victim) noexcept { assert(validSlots() + victim->validSlots() >= NodeType::minSlots()); assert(!getFrozen()); @@ -207,7 +204,7 @@ stealSomeFromRightNode(NodeType *victim) template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void -BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::cleanRange(uint32_t from, uint32_t to) +BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::cleanRange(uint32_t from, uint32_t to) noexcept { assert(from < to); assert(to <= validSlots()); @@ -224,7 +221,7 @@ BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::cleanRange(uint32_t from, uint32_t to template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void -BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::clean() +BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::clean() noexcept { if (validSlots() == 0) return; @@ -235,7 +232,7 @@ BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::clean() template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> void -BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::cleanFrozen() +BTreeNodeTT<KeyT, DataT, AggrT, NumSlots>::cleanFrozen() noexcept { assert(validSlots() <= NodeType::maxSlots()); assert(getFrozen()); @@ -256,8 +253,7 @@ template <typename NodeAllocatorType> void BTreeInternalNode<KeyT, AggrT, NumSlots>:: splitInsert(BTreeInternalNode *splitNode, uint32_t idx, const KeyT &key, - const BTreeNode::Ref &data, - NodeAllocatorType &allocator) + const BTreeNode::Ref &data, NodeAllocatorType &allocator) noexcept { assert(!getFrozen()); assert(!splitNode->getFrozen()); @@ -287,7 +283,7 @@ splitInsert(BTreeInternalNode *splitNode, uint32_t idx, const KeyT &key, template <typename KeyT, typename AggrT, uint32_t NumSlots> void BTreeInternalNode<KeyT, AggrT, NumSlots>:: -stealAllFromLeftNode(const BTreeInternalNode *victim) +stealAllFromLeftNode(const BTreeInternalNode *victim) noexcept { ParentType::stealAllFromLeftNode(victim); _validLeaves += victim->_validLeaves; @@ -296,7 +292,7 @@ stealAllFromLeftNode(const BTreeInternalNode *victim) template <typename KeyT, typename AggrT, uint32_t NumSlots> void BTreeInternalNode<KeyT, AggrT, NumSlots>:: -stealAllFromRightNode(const BTreeInternalNode *victim) +stealAllFromRightNode(const BTreeInternalNode *victim) noexcept { ParentType::stealAllFromRightNode(victim); _validLeaves += victim->_validLeaves; @@ -305,7 +301,7 @@ stealAllFromRightNode(const BTreeInternalNode *victim) template <typename KeyT, typename AggrT, uint32_t NumSlots> template <typename NodeAllocatorType> uint32_t -BTreeInternalNode<KeyT, AggrT, NumSlots>::countValidLeaves(uint32_t start, uint32_t end, NodeAllocatorType &allocator) +BTreeInternalNode<KeyT, AggrT, NumSlots>::countValidLeaves(uint32_t start, uint32_t end, NodeAllocatorType &allocator) noexcept { assert(start <= end); assert(end <= validSlots()); @@ -320,7 +316,7 @@ template <typename KeyT, typename AggrT, uint32_t NumSlots> template <typename NodeAllocatorType> void BTreeInternalNode<KeyT, AggrT, NumSlots>:: -stealSomeFromLeftNode(BTreeInternalNode *victim, NodeAllocatorType &allocator) +stealSomeFromLeftNode(BTreeInternalNode *victim, NodeAllocatorType &allocator) noexcept { uint16_t oldValidSlots = validSlots(); ParentType::stealSomeFromLeftNode(victim); @@ -334,7 +330,7 @@ template <typename KeyT, typename AggrT, uint32_t NumSlots> template <typename NodeAllocatorType> void BTreeInternalNode<KeyT, AggrT, NumSlots>:: -stealSomeFromRightNode(BTreeInternalNode *victim, NodeAllocatorType &allocator) +stealSomeFromRightNode(BTreeInternalNode *victim, NodeAllocatorType &allocator) noexcept { uint16_t oldValidSlots = validSlots(); ParentType::stealSomeFromRightNode(victim); @@ -346,7 +342,7 @@ stealSomeFromRightNode(BTreeInternalNode *victim, NodeAllocatorType &allocator) template <typename KeyT, typename AggrT, uint32_t NumSlots> void -BTreeInternalNode<KeyT, AggrT, NumSlots>::clean() +BTreeInternalNode<KeyT, AggrT, NumSlots>::clean() noexcept { ParentType::clean(); _validLeaves = 0; @@ -355,7 +351,7 @@ BTreeInternalNode<KeyT, AggrT, NumSlots>::clean() template <typename KeyT, typename AggrT, uint32_t NumSlots> void -BTreeInternalNode<KeyT, AggrT, NumSlots>::cleanFrozen() +BTreeInternalNode<KeyT, AggrT, NumSlots>::cleanFrozen() noexcept { ParentType::cleanFrozen(); _validLeaves = 0; @@ -364,7 +360,7 @@ BTreeInternalNode<KeyT, AggrT, NumSlots>::cleanFrozen() template <typename KeyT, typename AggrT, uint32_t NumSlots> template <typename NodeStoreType, typename FunctionType> void -BTreeInternalNode<KeyT, AggrT, NumSlots>::foreach_key(NodeStoreType &store, FunctionType func) const { +BTreeInternalNode<KeyT, AggrT, NumSlots>::foreach_key(NodeStoreType &store, FunctionType func) const noexcept { const BTreeNode::ChildRef *it = this->_data; const BTreeNode::ChildRef *ite = it + _validSlots; if (this->getLevel() > 1u) { @@ -385,7 +381,7 @@ BTreeInternalNode<KeyT, AggrT, NumSlots>::foreach_key(NodeStoreType &store, Func template <typename KeyT, typename AggrT, uint32_t NumSlots> template <typename NodeStoreType, typename FunctionType> void -BTreeInternalNode<KeyT, AggrT, NumSlots>::foreach_key_range(NodeStoreType &store, uint32_t start_idx, uint32_t end_idx, FunctionType func) const { +BTreeInternalNode<KeyT, AggrT, NumSlots>::foreach_key_range(NodeStoreType &store, uint32_t start_idx, uint32_t end_idx, FunctionType func) const noexcept { const BTreeNode::ChildRef *it = this->_data; const BTreeNode::ChildRef *ite = it + end_idx; it += start_idx; @@ -403,7 +399,7 @@ BTreeInternalNode<KeyT, AggrT, NumSlots>::foreach_key_range(NodeStoreType &store template <typename KeyT, typename AggrT, uint32_t NumSlots> template <typename NodeStoreType, typename FunctionType> void -BTreeInternalNode<KeyT, AggrT, NumSlots>::foreach(NodeStoreType &store, FunctionType func) const { +BTreeInternalNode<KeyT, AggrT, NumSlots>::foreach(NodeStoreType &store, FunctionType func) const noexcept { const BTreeNode::ChildRef *it = this->_data; const BTreeNode::ChildRef *ite = it + _validSlots; if (this->getLevel() > 1u) { @@ -436,7 +432,7 @@ BTreeLeafNode(const KeyDataType *smallArray, uint32_t arraySize) noexcept template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> template <typename FunctionType> void -BTreeLeafNode<KeyT, DataT, AggrT, NumSlots>::foreach_key(FunctionType func) const { +BTreeLeafNode<KeyT, DataT, AggrT, NumSlots>::foreach_key(FunctionType func) const noexcept { const KeyT *it = _keys; const KeyT *ite = it + _validSlots; for (; it != ite; ++it) { @@ -450,7 +446,7 @@ BTreeLeafNode<KeyT, DataT, AggrT, NumSlots>::foreach_key(FunctionType func) cons template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> template <typename FunctionType> void -BTreeLeafNode<KeyT, DataT, AggrT, NumSlots>::foreach_key_range(uint32_t start_idx, uint32_t end_idx, FunctionType func) const { +BTreeLeafNode<KeyT, DataT, AggrT, NumSlots>::foreach_key_range(uint32_t start_idx, uint32_t end_idx, FunctionType func) const noexcept { const KeyT *it = _keys; const KeyT *ite = it + end_idx; it += start_idx; @@ -462,7 +458,7 @@ BTreeLeafNode<KeyT, DataT, AggrT, NumSlots>::foreach_key_range(uint32_t start_id template <typename KeyT, typename DataT, typename AggrT, uint32_t NumSlots> template <typename FunctionType> void -BTreeLeafNode<KeyT, DataT, AggrT, NumSlots>::foreach(FunctionType func) const { +BTreeLeafNode<KeyT, DataT, AggrT, NumSlots>::foreach(FunctionType func) const noexcept { const KeyT *it = _keys; const KeyT *ite = it + _validSlots; uint32_t idx = 0; diff --git a/vespalib/src/vespa/vespalib/btree/btreenodeallocator.h b/vespalib/src/vespa/vespalib/btree/btreenodeallocator.h index e36d1507495..02d6d7f6969 100644 --- a/vespalib/src/vespa/vespalib/btree/btreenodeallocator.h +++ b/vespalib/src/vespa/vespalib/btree/btreenodeallocator.h @@ -54,7 +54,7 @@ public: BTreeNodeAllocator(); ~BTreeNodeAllocator(); - void disableFreeLists() { + void disableFreeLists() noexcept { _nodeStore.disableFreeLists(); } @@ -111,57 +111,57 @@ public: void reclaim_all_memory(); - static bool isValidRef(BTreeNode::Ref ref) { return NodeStore::isValidRef(ref); } + static bool isValidRef(BTreeNode::Ref ref) noexcept { return NodeStore::isValidRef(ref); } - bool isLeafRef(BTreeNode::Ref ref) const { + bool isLeafRef(BTreeNode::Ref ref) const noexcept { if (!isValidRef(ref)) return false; return _nodeStore.isLeafRef(ref); } - const InternalNodeType *mapInternalRef(BTreeNode::Ref ref) const { + const InternalNodeType *mapInternalRef(BTreeNode::Ref ref) const noexcept { return _nodeStore.mapInternalRef(ref); } - InternalNodeType *mapInternalRef(BTreeNode::Ref ref) { + InternalNodeType *mapInternalRef(BTreeNode::Ref ref) noexcept { return _nodeStore.mapInternalRef(ref); } - const LeafNodeType *mapLeafRef(BTreeNode::Ref ref) const { + const LeafNodeType *mapLeafRef(BTreeNode::Ref ref) const noexcept { return _nodeStore.mapLeafRef(ref); } - LeafNodeType *mapLeafRef(BTreeNode::Ref ref) { + LeafNodeType *mapLeafRef(BTreeNode::Ref ref) noexcept { return _nodeStore.mapLeafRef(ref); } template <typename NodeType> - const NodeType *mapRef(BTreeNode::Ref ref) const { + const NodeType *mapRef(BTreeNode::Ref ref) const noexcept { return _nodeStore.template mapRef<NodeType>(ref); } template <typename NodeType> - NodeType *mapRef(BTreeNode::Ref ref) { + NodeType *mapRef(BTreeNode::Ref ref) noexcept { return _nodeStore.template mapRef<NodeType>(ref); } InternalNodeTypeRefPair moveInternalNode(const InternalNodeType *node); LeafNodeTypeRefPair moveLeafNode(const LeafNodeType *node); - uint32_t validLeaves(BTreeNode::Ref ref) const; + uint32_t validLeaves(BTreeNode::Ref ref) const noexcept; /* * Extract level from ref. */ - uint32_t getLevel(BTreeNode::Ref ref) const; - const KeyT &getLastKey(BTreeNode::Ref node) const; - const AggrT &getAggregated(BTreeNode::Ref node) const; + uint32_t getLevel(BTreeNode::Ref ref) const noexcept; + const KeyT &getLastKey(BTreeNode::Ref node) const noexcept; + const AggrT &getAggregated(BTreeNode::Ref node) const noexcept; - vespalib::MemoryUsage getMemoryUsage() const; + vespalib::MemoryUsage getMemoryUsage() const noexcept; vespalib::string toString(BTreeNode::Ref ref) const; vespalib::string toString(const BTreeNode * node) const; - bool getCompacting(EntryRef ref) { return _nodeStore.getCompacting(ref); } + bool getCompacting(EntryRef ref) noexcept { return _nodeStore.getCompacting(ref); } std::unique_ptr<vespalib::datastore::CompactingBuffers> start_compact_worst(const CompactionStrategy& compaction_strategy) { return _nodeStore.start_compact_worst(compaction_strategy); } @@ -175,7 +175,7 @@ public: _nodeStore.foreach(ref, func); } - const NodeStore &getNodeStore() const { return _nodeStore; } + const NodeStore &getNodeStore() const noexcept { return _nodeStore; } }; extern template class BTreeNodeAllocator<uint32_t, uint32_t, NoAggregated, BTreeDefaultTraits::INTERNAL_SLOTS, BTreeDefaultTraits::LEAF_SLOTS>; diff --git a/vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp b/vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp index 69db7ad579c..fcc086fe411 100644 --- a/vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp +++ b/vespalib/src/vespa/vespalib/btree/btreenodeallocator.hpp @@ -147,10 +147,9 @@ BTreeNode::Ref BTreeNodeAllocator<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS>:: thawNode(BTreeNode::Ref node) { - if (isLeafRef(node)) - return thawNode(node, mapLeafRef(node)).ref; - else - return thawNode(node, mapInternalRef(node)).ref; + return isLeafRef(node) + ? thawNode(node, mapLeafRef(node)).ref + : thawNode(node, mapInternalRef(node)).ref; } @@ -158,8 +157,7 @@ template <typename KeyT, typename DataT, typename AggrT, size_t INTERNAL_SLOTS, size_t LEAF_SLOTS> void BTreeNodeAllocator<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS>:: -holdNode(BTreeNode::Ref nodeRef, - InternalNodeType *node) +holdNode(BTreeNode::Ref nodeRef, InternalNodeType *node) { if (node->getFrozen()) { _nodeStore.hold_entry(nodeRef); @@ -174,8 +172,7 @@ template <typename KeyT, typename DataT, typename AggrT, size_t INTERNAL_SLOTS, size_t LEAF_SLOTS> void BTreeNodeAllocator<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS>:: -holdNode(BTreeNode::Ref nodeRef, - LeafNodeType *node) +holdNode(BTreeNode::Ref nodeRef, LeafNodeType *node) { if (node->getFrozen()) { _nodeStore.hold_entry(nodeRef); @@ -318,12 +315,11 @@ template <typename KeyT, typename DataT, typename AggrT, size_t INTERNAL_SLOTS, size_t LEAF_SLOTS> uint32_t BTreeNodeAllocator<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS>:: -validLeaves(BTreeNode::Ref ref) const +validLeaves(BTreeNode::Ref ref) const noexcept { - if (isLeafRef(ref)) - return mapLeafRef(ref)->validSlots(); - else - return mapInternalRef(ref)->validLeaves(); + return isLeafRef(ref) + ? mapLeafRef(ref)->validSlots() + : mapInternalRef(ref)->validLeaves(); } @@ -331,12 +327,11 @@ template <typename KeyT, typename DataT, typename AggrT, size_t INTERNAL_SLOTS, size_t LEAF_SLOTS> uint32_t BTreeNodeAllocator<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS>:: -getLevel(BTreeNode::Ref ref) const +getLevel(BTreeNode::Ref ref) const noexcept { - if (isLeafRef(ref)) - return BTreeNode::LEAF_LEVEL; - else - return mapInternalRef(ref)->getLevel(); + return isLeafRef(ref) + ? BTreeNode::LEAF_LEVEL + : mapInternalRef(ref)->getLevel(); } @@ -344,12 +339,11 @@ template <typename KeyT, typename DataT, typename AggrT, size_t INTERNAL_SLOTS, size_t LEAF_SLOTS> const KeyT & BTreeNodeAllocator<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS>:: -getLastKey(BTreeNode::Ref node) const +getLastKey(BTreeNode::Ref node) const noexcept { - if (isLeafRef(node)) - return mapLeafRef(node)->getLastKey(); - else - return mapInternalRef(node)->getLastKey(); + return isLeafRef(node) + ? mapLeafRef(node)->getLastKey() + : mapInternalRef(node)->getLastKey(); } @@ -357,7 +351,7 @@ template <typename KeyT, typename DataT, typename AggrT, size_t INTERNAL_SLOTS, size_t LEAF_SLOTS> const AggrT & BTreeNodeAllocator<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS>:: -getAggregated(BTreeNode::Ref node) const +getAggregated(BTreeNode::Ref node) const noexcept { if (!node.valid()) return LeafNodeType::getEmptyAggregated(); @@ -372,10 +366,9 @@ template <typename KeyT, typename DataT, typename AggrT, size_t INTERNAL_SLOTS, size_t LEAF_SLOTS> vespalib::MemoryUsage BTreeNodeAllocator<KeyT, DataT, AggrT, INTERNAL_SLOTS, LEAF_SLOTS>:: -getMemoryUsage() const +getMemoryUsage() const noexcept { - vespalib::MemoryUsage usage = _nodeStore.getMemoryUsage(); - return usage; + return _nodeStore.getMemoryUsage(); } template <typename KeyT, typename DataT, typename AggrT, diff --git a/vespalib/src/vespa/vespalib/btree/btreenodestore.h b/vespalib/src/vespa/vespalib/btree/btreenodestore.h index ba316465d90..414d5adc572 100644 --- a/vespalib/src/vespa/vespalib/btree/btreenodestore.h +++ b/vespalib/src/vespa/vespalib/btree/btreenodestore.h @@ -13,7 +13,7 @@ namespace vespalib::btree { class BTreeNodeReclaimer { public: - static void reclaim(BTreeNode * node) { + static void reclaim(BTreeNode * node) noexcept { node->unFreeze(); } }; @@ -78,44 +78,44 @@ public: ~BTreeNodeStore(); - void disableFreeLists() { _store.disableFreeLists(); } + void disableFreeLists() noexcept { _store.disableFreeLists(); } void disable_entry_hold_list() { _store.disable_entry_hold_list(); } - static bool isValidRef(EntryRef ref) { return ref.valid(); } + static bool isValidRef(EntryRef ref) noexcept { return ref.valid(); } - bool isLeafRef(EntryRef ref) const { + bool isLeafRef(EntryRef ref) const noexcept { RefType iRef(ref); return _store.getTypeId(iRef.bufferId()) == NODETYPE_LEAF; } - const InternalNodeType *mapInternalRef(EntryRef ref) const { + const InternalNodeType *mapInternalRef(EntryRef ref) const noexcept { RefType iRef(ref); return _store.getEntry<InternalNodeType>(iRef); } - InternalNodeType *mapInternalRef(EntryRef ref) { + InternalNodeType *mapInternalRef(EntryRef ref) noexcept { RefType iRef(ref); return _store.getEntry<InternalNodeType>(iRef); } - const LeafNodeType *mapLeafRef(EntryRef ref) const { + const LeafNodeType *mapLeafRef(EntryRef ref) const noexcept { RefType iRef(ref); return _store.getEntry<LeafNodeType>(iRef); } - LeafNodeType *mapLeafRef(EntryRef ref) { + LeafNodeType *mapLeafRef(EntryRef ref) noexcept { RefType iRef(ref); return _store.getEntry<LeafNodeType>(iRef); } template <typename NodeType> - const NodeType *mapRef(EntryRef ref) const { + const NodeType *mapRef(EntryRef ref) const noexcept { RefType iRef(ref); return _store.getEntry<NodeType>(iRef); } template <typename NodeType> - NodeType *mapRef(EntryRef ref) { + NodeType *mapRef(EntryRef ref) noexcept { RefType iRef(ref); return _store.getEntry<NodeType>(iRef); } @@ -163,7 +163,7 @@ public: } // Inherit doc from DataStoreBase - datastore::MemoryStats getMemStats() const { + datastore::MemoryStats getMemStats() const noexcept { return _store.getMemStats(); } @@ -177,16 +177,16 @@ public: } // Inherit doc from DataStoreBase - vespalib::MemoryUsage getMemoryUsage() const { + vespalib::MemoryUsage getMemoryUsage() const noexcept { return _store.getMemoryUsage(); } // Inherit doc from DataStoreT - bool getCompacting(EntryRef ref) { + bool getCompacting(EntryRef ref) noexcept { return _store.getCompacting(ref); } - bool has_held_buffers() const { + bool has_held_buffers() const noexcept { return _store.has_held_buffers(); } diff --git a/vespalib/src/vespa/vespalib/btree/btreenodestore.hpp b/vespalib/src/vespa/vespalib/btree/btreenodestore.hpp index 8c65838e65e..bc9a27af3ad 100644 --- a/vespalib/src/vespa/vespalib/btree/btreenodestore.hpp +++ b/vespalib/src/vespa/vespalib/btree/btreenodestore.hpp @@ -14,7 +14,7 @@ void BTreeNodeBufferType<EntryType>::initialize_reserved_entries(void *buffer, EntryCount reserved_entries) { ParentType::initialize_reserved_entries(buffer, reserved_entries); - EntryType *e = static_cast<EntryType *>(buffer); + auto *e = static_cast<EntryType *>(buffer); for (size_t j = reserved_entries; j != 0; --j) { e->freeze(); ++e; diff --git a/vespalib/src/vespa/vespalib/data/memorydatastore.h b/vespalib/src/vespa/vespalib/data/memorydatastore.h index 0bf2becf7c3..3682e3629e3 100644 --- a/vespalib/src/vespa/vespalib/data/memorydatastore.h +++ b/vespalib/src/vespa/vespalib/data/memorydatastore.h @@ -2,7 +2,6 @@ #pragma once #include <vespa/vespalib/util/alloc.h> -#include <vespa/vespalib/util/array.h> #include <vector> #include <mutex> diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp b/vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp index d44c2e45b2b..b77d9abe22b 100644 --- a/vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp +++ b/vespalib/src/vespa/vespalib/datastore/buffer_free_list.cpp @@ -14,13 +14,13 @@ BufferFreeList::attach() } void -BufferFreeList::detach() +BufferFreeList::detach() noexcept { assert(_free_list != nullptr); _free_list->detach(*this); } -BufferFreeList::BufferFreeList(std::atomic<EntryCount>& dead_entries) +BufferFreeList::BufferFreeList(std::atomic<EntryCount>& dead_entries) noexcept : _dead_entries(dead_entries), _free_list(), _free_refs() @@ -34,7 +34,7 @@ BufferFreeList::~BufferFreeList() } void -BufferFreeList::enable(FreeList& free_list) +BufferFreeList::enable(FreeList& free_list) noexcept { assert(_free_list == nullptr); assert(_free_refs.empty()); @@ -42,7 +42,7 @@ BufferFreeList::enable(FreeList& free_list) } void -BufferFreeList::disable() +BufferFreeList::disable() noexcept { if (!empty()) { detach(); @@ -59,7 +59,7 @@ BufferFreeList::push_entry(EntryRef ref) { _free_refs.push_back(ref); } EntryRef -BufferFreeList::pop_entry() { +BufferFreeList::pop_entry() noexcept { EntryRef ret = _free_refs.back(); _free_refs.pop_back(); if (empty()) { diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_free_list.h b/vespalib/src/vespa/vespalib/datastore/buffer_free_list.h index 48fd2e0347c..4491f0638d3 100644 --- a/vespalib/src/vespa/vespalib/datastore/buffer_free_list.h +++ b/vespalib/src/vespa/vespalib/datastore/buffer_free_list.h @@ -4,7 +4,6 @@ #include "entryref.h" #include "buffer_type.h" -#include <vespa/vespalib/util/array.h> namespace vespalib::datastore { @@ -17,29 +16,29 @@ class FreeList; */ class BufferFreeList { private: - using EntryRefArray = vespalib::Array<EntryRef>; + using EntryRefArray = std::vector<EntryRef>; std::atomic<EntryCount>& _dead_entries; - FreeList* _free_list; - EntryRefArray _free_refs; + FreeList *_free_list; + EntryRefArray _free_refs; void attach(); - void detach(); + void detach() noexcept; public: - BufferFreeList(std::atomic<EntryCount>& dead_entrie); + explicit BufferFreeList(std::atomic<EntryCount>& dead_entries) noexcept; ~BufferFreeList(); - BufferFreeList(BufferFreeList&&) = default; // Needed for emplace_back() during setup. + BufferFreeList(BufferFreeList&&) noexcept = default; // Needed for emplace_back() during setup. BufferFreeList(const BufferFreeList&) = delete; BufferFreeList& operator=(const BufferFreeList&) = delete; BufferFreeList& operator=(BufferFreeList&&) = delete; - void enable(FreeList& free_list); - void disable(); + void enable(FreeList& free_list) noexcept; + void disable() noexcept; - bool enabled() const { return _free_list != nullptr; } - bool empty() const { return _free_refs.empty(); } + bool enabled() const noexcept { return _free_list != nullptr; } + bool empty() const noexcept { return _free_refs.empty(); } void push_entry(EntryRef ref); - EntryRef pop_entry(); + EntryRef pop_entry() noexcept; }; } diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp b/vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp index b1fd6460d24..5705d9faefc 100644 --- a/vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp +++ b/vespalib/src/vespa/vespalib/datastore/buffer_stats.cpp @@ -5,7 +5,7 @@ namespace vespalib::datastore { -BufferStats::BufferStats() +BufferStats::BufferStats() noexcept : _alloc_entries(0), _used_entries(0), _hold_entries(0), @@ -16,7 +16,7 @@ BufferStats::BufferStats() } void -BufferStats::add_to_mem_stats(size_t entry_size, MemoryStats& stats) const +BufferStats::add_to_mem_stats(size_t entry_size, MemoryStats& stats) const noexcept { size_t extra_used = extra_used_bytes(); stats._alloc_entries += capacity(); @@ -29,13 +29,13 @@ BufferStats::add_to_mem_stats(size_t entry_size, MemoryStats& stats) const stats._holdBytes += (hold_entries() * entry_size) + extra_hold_bytes(); } -InternalBufferStats::InternalBufferStats() +InternalBufferStats::InternalBufferStats() noexcept : BufferStats() { } void -InternalBufferStats::clear() +InternalBufferStats::clear() noexcept { _alloc_entries.store(0, std::memory_order_relaxed); _used_entries.store(0, std::memory_order_relaxed); @@ -46,7 +46,7 @@ InternalBufferStats::clear() } void -InternalBufferStats::dec_hold_entries(size_t value) +InternalBufferStats::dec_hold_entries(size_t value) noexcept { EntryCount elems = hold_entries(); assert(elems >= value); diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_stats.h b/vespalib/src/vespa/vespalib/datastore/buffer_stats.h index 12ac8ae4995..59446ddc989 100644 --- a/vespalib/src/vespa/vespalib/datastore/buffer_stats.h +++ b/vespalib/src/vespa/vespalib/datastore/buffer_stats.h @@ -32,24 +32,24 @@ protected: std::atomic<size_t> _extra_hold_bytes; public: - BufferStats(); + BufferStats() noexcept; - size_t size() const { return _used_entries.load(std::memory_order_relaxed); } - size_t capacity() const { return _alloc_entries.load(std::memory_order_relaxed); } - size_t remaining() const { return capacity() - size(); } + size_t size() const noexcept { return _used_entries.load(std::memory_order_relaxed); } + size_t capacity() const noexcept { return _alloc_entries.load(std::memory_order_relaxed); } + size_t remaining() const noexcept { return capacity() - size(); } - void pushed_back(size_t num_entries) { + void pushed_back(size_t num_entries) noexcept { _used_entries.store(size() + num_entries, std::memory_order_relaxed); } - size_t dead_entries() const { return _dead_entries.load(std::memory_order_relaxed); } - size_t hold_entries() const { return _hold_entries.load(std::memory_order_relaxed); } - size_t extra_used_bytes() const { return _extra_used_bytes.load(std::memory_order_relaxed); } - size_t extra_hold_bytes() const { return _extra_hold_bytes.load(std::memory_order_relaxed); } + size_t dead_entries() const noexcept { return _dead_entries.load(std::memory_order_relaxed); } + size_t hold_entries() const noexcept { return _hold_entries.load(std::memory_order_relaxed); } + size_t extra_used_bytes() const noexcept { return _extra_used_bytes.load(std::memory_order_relaxed); } + size_t extra_hold_bytes() const noexcept { return _extra_hold_bytes.load(std::memory_order_relaxed); } - void inc_extra_used_bytes(size_t value) { _extra_used_bytes.store(extra_used_bytes() + value, std::memory_order_relaxed); } + void inc_extra_used_bytes(size_t value) noexcept { _extra_used_bytes.store(extra_used_bytes() + value, std::memory_order_relaxed); } - void add_to_mem_stats(size_t entry_size, MemoryStats& stats) const; + void add_to_mem_stats(size_t entry_size, MemoryStats& stats) const noexcept; }; /** @@ -57,19 +57,19 @@ public: */ class InternalBufferStats : public BufferStats { public: - InternalBufferStats(); - void clear(); - void set_alloc_entries(size_t value) { _alloc_entries.store(value, std::memory_order_relaxed); } - void set_dead_entries(size_t value) { _dead_entries.store(value, std::memory_order_relaxed); } - void set_hold_entries(size_t value) { _hold_entries.store(value, std::memory_order_relaxed); } - void inc_dead_entries(size_t value) { _dead_entries.store(dead_entries() + value, std::memory_order_relaxed); } - void inc_hold_entries(size_t value) { _hold_entries.store(hold_entries() + value, std::memory_order_relaxed); } - void dec_hold_entries(size_t value); - void inc_extra_hold_bytes(size_t value) { _extra_hold_bytes.store(extra_hold_bytes() + value, std::memory_order_relaxed); } - std::atomic<EntryCount>& used_entries_ref() { return _used_entries; } - std::atomic<EntryCount>& dead_entries_ref() { return _dead_entries; } - std::atomic<size_t>& extra_used_bytes_ref() { return _extra_used_bytes; } - std::atomic<size_t>& extra_hold_bytes_ref() { return _extra_hold_bytes; } + InternalBufferStats() noexcept; + void clear() noexcept; + void set_alloc_entries(size_t value) noexcept { _alloc_entries.store(value, std::memory_order_relaxed); } + void set_dead_entries(size_t value) noexcept { _dead_entries.store(value, std::memory_order_relaxed); } + void set_hold_entries(size_t value) noexcept { _hold_entries.store(value, std::memory_order_relaxed); } + void inc_dead_entries(size_t value) noexcept { _dead_entries.store(dead_entries() + value, std::memory_order_relaxed); } + void inc_hold_entries(size_t value) noexcept { _hold_entries.store(hold_entries() + value, std::memory_order_relaxed); } + void dec_hold_entries(size_t value) noexcept; + void inc_extra_hold_bytes(size_t value) noexcept { _extra_hold_bytes.store(extra_hold_bytes() + value, std::memory_order_relaxed); } + std::atomic<EntryCount>& used_entries_ref() noexcept { return _used_entries; } + std::atomic<EntryCount>& dead_entries_ref() noexcept { return _dead_entries; } + std::atomic<size_t>& extra_used_bytes_ref() noexcept { return _extra_used_bytes; } + std::atomic<size_t>& extra_hold_bytes_ref() noexcept { return _extra_hold_bytes; } }; } diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_type.cpp b/vespalib/src/vespa/vespalib/datastore/buffer_type.cpp index ca15a5cc5fd..b593b44adfc 100644 --- a/vespalib/src/vespa/vespalib/datastore/buffer_type.cpp +++ b/vespalib/src/vespa/vespalib/datastore/buffer_type.cpp @@ -16,7 +16,7 @@ constexpr float DEFAULT_ALLOC_GROW_FACTOR = 0.2; } void -BufferTypeBase::CleanContext::extraBytesCleaned(size_t value) +BufferTypeBase::CleanContext::extraBytesCleaned(size_t value) noexcept { size_t extra_used_bytes = _extraUsedBytes.load(std::memory_order_relaxed); size_t extra_hold_bytes = _extraHoldBytes.load(std::memory_order_relaxed); @@ -68,7 +68,7 @@ BufferTypeBase::~BufferTypeBase() } EntryCount -BufferTypeBase::get_reserved_entries(uint32_t bufferId) const +BufferTypeBase::get_reserved_entries(uint32_t bufferId) const noexcept { return bufferId == 0 ? 1u : 0u; } @@ -99,7 +99,7 @@ BufferTypeBase::on_hold(uint32_t buffer_id, const std::atomic<EntryCount>* used_ } void -BufferTypeBase::on_free(EntryCount used_entries) +BufferTypeBase::on_free(EntryCount used_entries) noexcept { --_holdBuffers; assert(_hold_used_entries >= used_entries); @@ -130,7 +130,7 @@ BufferTypeBase::is_dynamic_array_buffer_type() const noexcept } void -BufferTypeBase::clamp_max_entries(uint32_t max_entries) +BufferTypeBase::clamp_max_entries(uint32_t max_entries) noexcept { _max_entries = std::min(_max_entries, max_entries); _min_entries = std::min(_min_entries, _max_entries); @@ -186,7 +186,7 @@ BufferTypeBase::calc_entries_to_alloc(uint32_t bufferId, EntryCount free_entries } uint32_t -BufferTypeBase::get_scaled_num_entries_for_new_buffer() const +BufferTypeBase::get_scaled_num_entries_for_new_buffer() const noexcept { uint32_t active_buffers_count = get_active_buffers_count(); if (active_buffers_count <= 1u || _num_entries_for_new_buffer == 0u) { @@ -200,7 +200,7 @@ BufferTypeBase::get_scaled_num_entries_for_new_buffer() const return scaled_result; } -BufferTypeBase::AggregatedBufferCounts::AggregatedBufferCounts() +BufferTypeBase::AggregatedBufferCounts::AggregatedBufferCounts() noexcept : _counts() { } @@ -226,7 +226,7 @@ BufferTypeBase::AggregatedBufferCounts::remove_buffer(const std::atomic<EntryCou } BufferTypeBase::BufferCounts -BufferTypeBase::AggregatedBufferCounts::last_buffer() const +BufferTypeBase::AggregatedBufferCounts::last_buffer() const noexcept { BufferCounts result; assert(!_counts.empty()); @@ -237,7 +237,7 @@ BufferTypeBase::AggregatedBufferCounts::last_buffer() const } BufferTypeBase::BufferCounts -BufferTypeBase::AggregatedBufferCounts::all_buffers() const +BufferTypeBase::AggregatedBufferCounts::all_buffers() const noexcept { BufferCounts result; for (const auto& elem : _counts) { diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_type.h b/vespalib/src/vespa/vespalib/datastore/buffer_type.h index 3edafbc8e69..08e165afb98 100644 --- a/vespalib/src/vespa/vespalib/datastore/buffer_type.h +++ b/vespalib/src/vespa/vespalib/datastore/buffer_type.h @@ -28,11 +28,11 @@ public: std::atomic<size_t> &_extraUsedBytes; std::atomic<size_t> &_extraHoldBytes; public: - CleanContext(std::atomic<size_t>& extraUsedBytes, std::atomic<size_t>& extraHoldBytes) + CleanContext(std::atomic<size_t>& extraUsedBytes, std::atomic<size_t>& extraHoldBytes) noexcept : _extraUsedBytes(extraUsedBytes), _extraHoldBytes(extraHoldBytes) {} - void extraBytesCleaned(size_t value); + void extraBytesCleaned(size_t value) noexcept; }; BufferTypeBase(const BufferTypeBase &rhs) = delete; @@ -50,7 +50,7 @@ public: * Return number of reserved entries at start of buffer, to avoid * invalid reference. */ - virtual EntryCount get_reserved_entries(uint32_t bufferId) const; + virtual EntryCount get_reserved_entries(uint32_t bufferId) const noexcept; /** * Initialize reserved elements at start of buffer. @@ -62,7 +62,7 @@ public: size_t getArraySize() const noexcept { return _arraySize; } virtual void on_active(uint32_t bufferId, std::atomic<EntryCount>* used_entries, std::atomic<EntryCount>* dead_entries, void* buffer); void on_hold(uint32_t buffer_id, const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries); - virtual void on_free(EntryCount used_entries); + virtual void on_free(EntryCount used_entries) noexcept; void resume_primary_buffer(uint32_t buffer_id, std::atomic<EntryCount>* used_entries, std::atomic<EntryCount>* dead_entries); virtual const alloc::MemoryAllocator* get_memory_allocator() const; virtual bool is_dynamic_array_buffer_type() const noexcept; @@ -72,20 +72,20 @@ public: */ virtual size_t calc_entries_to_alloc(uint32_t bufferId, EntryCount free_entries_needed, bool resizing) const; - void clamp_max_entries(uint32_t max_entries); + void clamp_max_entries(uint32_t max_entries) noexcept; - uint32_t get_active_buffers_count() const { return _active_buffers.size(); } + uint32_t get_active_buffers_count() const noexcept { return _active_buffers.size(); } const std::vector<uint32_t>& get_active_buffers() const noexcept { return _active_buffers; } - size_t get_max_entries() const { return _max_entries; } - uint32_t get_scaled_num_entries_for_new_buffer() const; + size_t get_max_entries() const noexcept { return _max_entries; } + uint32_t get_scaled_num_entries_for_new_buffer() const noexcept; uint32_t get_num_entries_for_new_buffer() const noexcept { return _num_entries_for_new_buffer; } protected: struct BufferCounts { EntryCount used_entries; EntryCount dead_entries; - BufferCounts() : used_entries(0), dead_entries(0) {} - BufferCounts(EntryCount used_entries_in, EntryCount dead_entries_in) + BufferCounts() noexcept : used_entries(0), dead_entries(0) {} + BufferCounts(EntryCount used_entries_in, EntryCount dead_entries_in) noexcept : used_entries(used_entries_in), dead_entries(dead_entries_in) {} }; @@ -106,12 +106,12 @@ protected: std::vector<ActiveBufferCounts> _counts; public: - AggregatedBufferCounts(); + AggregatedBufferCounts() noexcept; void add_buffer(const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries); void remove_buffer(const std::atomic<EntryCount>* used_entries, const std::atomic<EntryCount>* dead_entries); - BufferCounts last_buffer() const; - BufferCounts all_buffers() const; - bool empty() const { return _counts.empty(); } + BufferCounts last_buffer() const noexcept; + BufferCounts all_buffers() const noexcept; + bool empty() const noexcept { return _counts.empty(); } }; uint32_t _entry_size; // Number of bytes in an allocation unit diff --git a/vespalib/src/vespa/vespalib/datastore/bufferstate.cpp b/vespalib/src/vespa/vespalib/datastore/bufferstate.cpp index 8a2f824ecb3..49f126d4a7c 100644 --- a/vespalib/src/vespa/vespalib/datastore/bufferstate.cpp +++ b/vespalib/src/vespa/vespalib/datastore/bufferstate.cpp @@ -10,7 +10,7 @@ using vespalib::alloc::MemoryAllocator; namespace vespalib::datastore { -BufferState::BufferState() +BufferState::BufferState() noexcept : _stats(), _free_list(_stats.dead_entries_ref()), _typeHandler(nullptr), @@ -36,11 +36,11 @@ namespace { struct AllocResult { size_t entries; size_t bytes; - AllocResult(size_t entries_, size_t bytes_) : entries(entries_), bytes(bytes_) {} + AllocResult(size_t entries_, size_t bytes_) noexcept : entries(entries_), bytes(bytes_) {} }; size_t -roundUpToMatchAllocator(size_t sz) +roundUpToMatchAllocator(size_t sz) noexcept { if (sz == 0) { return 0; @@ -57,10 +57,7 @@ roundUpToMatchAllocator(size_t sz) } AllocResult -calc_allocation(uint32_t bufferId, - BufferTypeBase &typeHandler, - size_t free_entries_needed, - bool resizing) +calc_allocation(uint32_t bufferId, BufferTypeBase &typeHandler, size_t free_entries_needed, bool resizing) { size_t alloc_entries = typeHandler.calc_entries_to_alloc(bufferId, free_entries_needed, resizing); size_t entry_size = typeHandler.entry_size(); @@ -72,16 +69,14 @@ calc_allocation(uint32_t bufferId, allocBytes = maxAllocBytes; } size_t adjusted_alloc_entries = (allocBytes - buffer_underflow_size) / entry_size; - return AllocResult(adjusted_alloc_entries, allocBytes); + return {adjusted_alloc_entries, allocBytes}; } } void -BufferState::on_active(uint32_t bufferId, uint32_t typeId, - BufferTypeBase *typeHandler, - size_t free_entries_needed, - std::atomic<void*>& buffer) +BufferState::on_active(uint32_t bufferId, uint32_t typeId, BufferTypeBase *typeHandler, + size_t free_entries_needed, std::atomic<void*>& buffer) { assert(buffer.load(std::memory_order_relaxed) == nullptr); assert(_buffer.get() == nullptr); @@ -207,15 +202,12 @@ BufferState::free_entries(EntryRef ref, size_t num_entries, size_t ref_offset) auto type_handler = getTypeHandler(); auto buffer_underflow_size = type_handler->buffer_underflow_size(); type_handler->clean_hold(get_buffer(buffer_underflow_size), ref_offset, num_entries, - BufferTypeBase::CleanContext(_stats.extra_used_bytes_ref(), - _stats.extra_hold_bytes_ref())); + BufferTypeBase::CleanContext(_stats.extra_used_bytes_ref(), _stats.extra_hold_bytes_ref())); } void -BufferState::fallback_resize(uint32_t bufferId, - size_t free_entries_needed, - std::atomic<void*>& buffer, - Alloc &holdBuffer) +BufferState::fallback_resize(uint32_t bufferId, size_t free_entries_needed, + std::atomic<void*>& buffer, Alloc &holdBuffer) { assert(getState() == State::ACTIVE); auto type_handler = getTypeHandler(); diff --git a/vespalib/src/vespa/vespalib/datastore/bufferstate.h b/vespalib/src/vespa/vespalib/datastore/bufferstate.h index 070982080ff..ad841ae3a18 100644 --- a/vespalib/src/vespa/vespalib/datastore/bufferstate.h +++ b/vespalib/src/vespa/vespalib/datastore/bufferstate.h @@ -31,11 +31,7 @@ class BufferState public: using Alloc = vespalib::alloc::Alloc; - enum class State : uint8_t { - FREE, - ACTIVE, - HOLD - }; + enum class State : uint8_t { FREE, ACTIVE, HOLD }; private: InternalBufferStats _stats; @@ -56,7 +52,7 @@ public: * compaction should always be used to free up whole buffers. */ - BufferState(); + BufferState() noexcept; BufferState(const BufferState &) = delete; BufferState & operator=(const BufferState &) = delete; ~BufferState(); @@ -103,31 +99,31 @@ public: */ void free_entries(EntryRef ref, size_t num_entries, size_t ref_offset); - BufferStats& stats() { return _stats; } - const BufferStats& stats() const { return _stats; } + BufferStats& stats() noexcept { return _stats; } + const BufferStats& stats() const noexcept { return _stats; } - void enable_free_list(FreeList& type_free_list) { _free_list.enable(type_free_list); } - void disable_free_list() { _free_list.disable(); } + void enable_free_list(FreeList& type_free_list) noexcept { _free_list.enable(type_free_list); } + void disable_free_list() noexcept { _free_list.disable(); } - size_t size() const { return _stats.size(); } - size_t capacity() const { return _stats.capacity(); } - size_t remaining() const { return _stats.remaining(); } + size_t size() const noexcept { return _stats.size(); } + size_t capacity() const noexcept { return _stats.capacity(); } + size_t remaining() const noexcept { return _stats.remaining(); } void dropBuffer(uint32_t buffer_id, std::atomic<void*>& buffer); - uint32_t getTypeId() const { return _typeId; } - uint32_t getArraySize() const { return _arraySize; } - bool getCompacting() const { return _compacting; } - void setCompacting() { _compacting = true; } + uint32_t getTypeId() const noexcept { return _typeId; } + uint32_t getArraySize() const noexcept { return _arraySize; } + bool getCompacting() const noexcept { return _compacting; } + void setCompacting() noexcept { _compacting = true; } void fallback_resize(uint32_t bufferId, size_t free_entries_needed, std::atomic<void*>& buffer, Alloc &holdBuffer); - bool isActive(uint32_t typeId) const { + bool isActive(uint32_t typeId) const noexcept { return (isActive() && (_typeId == typeId)); } - bool isActive() const { return (getState() == State::ACTIVE); } - bool isOnHold() const { return (getState() == State::HOLD); } - bool isFree() const { return (getState() == State::FREE); } - State getState() const { return _state.load(std::memory_order_relaxed); } - const BufferTypeBase *getTypeHandler() const { return _typeHandler.load(std::memory_order_relaxed); } - BufferTypeBase *getTypeHandler() { return _typeHandler.load(std::memory_order_relaxed); } + bool isActive() const noexcept { return (getState() == State::ACTIVE); } + bool isOnHold() const noexcept { return (getState() == State::HOLD); } + bool isFree() const noexcept { return (getState() == State::FREE); } + State getState() const noexcept { return _state.load(std::memory_order_relaxed); } + const BufferTypeBase *getTypeHandler() const noexcept { return _typeHandler.load(std::memory_order_relaxed); } + BufferTypeBase *getTypeHandler() noexcept { return _typeHandler.load(std::memory_order_relaxed); } void resume_primary_buffer(uint32_t buffer_id); }; @@ -141,7 +137,7 @@ public: uint32_t getTypeId() const noexcept { return _typeId; } uint32_t get_array_size() const noexcept { return _array_size; } BufferState * get_state_relaxed() noexcept { return _state.load(std::memory_order_relaxed); } - const BufferState * get_state_acquire() const { return _state.load(std::memory_order_acquire); } + const BufferState * get_state_acquire() const noexcept { return _state.load(std::memory_order_acquire); } uint32_t get_entry_size() const noexcept { return _entry_size; } void setTypeId(uint32_t typeId) noexcept { _typeId = typeId; } void set_array_size(uint32_t arraySize) noexcept { _array_size = arraySize; } diff --git a/vespalib/src/vespa/vespalib/datastore/datastore.h b/vespalib/src/vespa/vespalib/datastore/datastore.h index 0226c780cf1..b4fe9ce2ac7 100644 --- a/vespalib/src/vespa/vespalib/datastore/datastore.h +++ b/vespalib/src/vespa/vespalib/datastore/datastore.h @@ -49,7 +49,7 @@ public: void reclaim_all_entry_refs() override; - bool getCompacting(EntryRef ref) { + bool getCompacting(EntryRef ref) noexcept { return getBufferState(RefType(ref).bufferId()).getCompacting(); } diff --git a/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp b/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp index c15d4784cc9..fd1d2c9a8d1 100644 --- a/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp +++ b/vespalib/src/vespa/vespalib/datastore/datastorebase.cpp @@ -48,7 +48,7 @@ primary_buffer_too_dead(const BufferState &state) } DataStoreBase::FallbackHold::FallbackHold(size_t bytesSize, BufferState::Alloc &&buffer, size_t used_entries, - BufferTypeBase *typeHandler, uint32_t typeId) + BufferTypeBase *typeHandler, uint32_t typeId) noexcept : GenerationHeldBase(bytesSize), _buffer(std::move(buffer)), _used_entries(used_entries), @@ -68,7 +68,7 @@ class DataStoreBase::BufferHold : public GenerationHeldBase { uint32_t _bufferId; public: - BufferHold(size_t bytesSize, DataStoreBase &dsb, uint32_t bufferId) + BufferHold(size_t bytesSize, DataStoreBase &dsb, uint32_t bufferId) noexcept : GenerationHeldBase(bytesSize), _dsb(dsb), _bufferId(bufferId) @@ -159,7 +159,7 @@ DataStoreBase::consider_grow_active_buffer(uint32_t type_id, size_t entries_need } uint32_t -DataStoreBase::getFirstFreeBufferId() { +DataStoreBase::getFirstFreeBufferId() noexcept { uint32_t buffer_id = 0; for (auto & buffer : _buffers) { BufferState * state = buffer.get_state_relaxed(); @@ -268,7 +268,7 @@ DataStoreBase::dropBuffers() } vespalib::MemoryUsage -DataStoreBase::getDynamicMemoryUsage() const +DataStoreBase::getDynamicMemoryUsage() const noexcept { auto stats = getMemStats(); vespalib::MemoryUsage usage; @@ -280,7 +280,7 @@ DataStoreBase::getDynamicMemoryUsage() const } vespalib::MemoryUsage -DataStoreBase::getMemoryUsage() const { +DataStoreBase::getMemoryUsage() const noexcept { auto usage = getDynamicMemoryUsage(); size_t extra_allocated = 0; extra_allocated += _buffers.capacity() * sizeof(BufferAndMeta); @@ -319,7 +319,7 @@ DataStoreBase::enableFreeLists() } void -DataStoreBase::disableFreeLists() +DataStoreBase::disableFreeLists() noexcept { for_each_buffer([](BufferState & state) { state.disable_free_list(); }); _freeListsEnabled = false; @@ -335,7 +335,7 @@ DataStoreBase::disable_entry_hold_list() } MemoryStats -DataStoreBase::getMemStats() const +DataStoreBase::getMemStats() const noexcept { MemoryStats stats; @@ -368,7 +368,7 @@ DataStoreBase::getMemStats() const } vespalib::AddressSpace -DataStoreBase::getAddressSpaceUsage() const +DataStoreBase::getAddressSpaceUsage() const noexcept { uint32_t buffer_id_limit = get_bufferid_limit_acquire(); size_t used_entries = 0; @@ -520,7 +520,7 @@ DataStoreBase::start_compact_worst_buffers(CompactionSpec compaction_spec, const } void -DataStoreBase::inc_hold_buffer_count() +DataStoreBase::inc_hold_buffer_count() noexcept { assert(_hold_buffer_count < std::numeric_limits<uint32_t>::max()); ++_hold_buffer_count; diff --git a/vespalib/src/vespa/vespalib/datastore/datastorebase.h b/vespalib/src/vespa/vespalib/datastore/datastorebase.h index bce2d2096f2..fb525f9378b 100644 --- a/vespalib/src/vespa/vespalib/datastore/datastorebase.h +++ b/vespalib/src/vespa/vespalib/datastore/datastorebase.h @@ -64,10 +64,10 @@ public: */ void switch_primary_buffer(uint32_t typeId, size_t entries_needed); - vespalib::MemoryUsage getMemoryUsage() const; - vespalib::MemoryUsage getDynamicMemoryUsage() const; + vespalib::MemoryUsage getMemoryUsage() const noexcept; + vespalib::MemoryUsage getDynamicMemoryUsage() const noexcept; - vespalib::AddressSpace getAddressSpaceUsage() const; + vespalib::AddressSpace getAddressSpaceUsage() const noexcept; /** * Get the primary buffer id for the given type id. @@ -135,7 +135,7 @@ public: /** * Disable free list management. */ - void disableFreeLists(); + void disableFreeLists() noexcept; void disable_entry_hold_list(); bool has_free_lists_enabled() const { return _freeListsEnabled; } @@ -143,38 +143,38 @@ public: /** * Returns the free list for the given type id. */ - FreeList &getFreeList(uint32_t typeId) { + FreeList &getFreeList(uint32_t typeId) noexcept { return _free_lists[typeId]; } /** * Returns aggregated memory statistics for all buffers in this data store. */ - MemoryStats getMemStats() const; + MemoryStats getMemStats() const noexcept; /** * Assume that no readers are present while data structure is being initialized. */ - void setInitializing(bool initializing) { _initializing = initializing; } + void setInitializing(bool initializing) noexcept { _initializing = initializing; } - uint32_t getTypeId(uint32_t bufferId) const { + uint32_t getTypeId(uint32_t bufferId) const noexcept { return _buffers[bufferId].getTypeId(); } void finishCompact(const std::vector<uint32_t> &toHold); - vespalib::GenerationHolder &getGenerationHolder() { + vespalib::GenerationHolder &getGenerationHolder() noexcept { return _genHolder; } // need object location before construction - static vespalib::GenerationHolder &getGenerationHolderLocation(DataStoreBase &self) { + static vespalib::GenerationHolder &getGenerationHolderLocation(DataStoreBase &self) noexcept { return self._genHolder; } std::unique_ptr<CompactingBuffers> start_compact_worst_buffers(CompactionSpec compaction_spec, const CompactionStrategy &compaction_strategy); - uint64_t get_compaction_count() const { return _compaction_count.load(std::memory_order_relaxed); } - void inc_compaction_count() const { ++_compaction_count; } + uint64_t get_compaction_count() const noexcept { return _compaction_count.load(std::memory_order_relaxed); } + void inc_compaction_count() const noexcept { ++_compaction_count; } bool has_held_buffers() const noexcept { return _hold_buffer_count != 0u; } /** @@ -184,9 +184,9 @@ public: */ virtual void reclaim_entry_refs(generation_t oldest_used_gen) = 0; - uint32_t get_entry_size(uint32_t type_id) { return _typeHandlers[type_id]->entry_size(); } + uint32_t get_entry_size(uint32_t type_id) noexcept { return _typeHandlers[type_id]->entry_size(); } - void* getBuffer(uint32_t bufferId) { return _buffers[bufferId].get_buffer_relaxed(); } + void* getBuffer(uint32_t bufferId) noexcept { return _buffers[bufferId].get_buffer_relaxed(); } protected: DataStoreBase(uint32_t numBuffers, uint32_t offset_bits, size_t max_entries); @@ -196,7 +196,7 @@ protected: EntryRef ref; size_t num_entries; - EntryRefHoldElem(EntryRef ref_in, size_t num_entries_in) + EntryRefHoldElem(EntryRef ref_in, size_t num_entries_in) noexcept : ref(ref_in), num_entries(num_entries_in) {} @@ -223,7 +223,7 @@ private: uint32_t _typeId; FallbackHold(size_t bytesSize, BufferState::Alloc &&buffer, size_t used_entries, - BufferTypeBase *typeHandler, uint32_t typeId); + BufferTypeBase *typeHandler, uint32_t typeId) noexcept; ~FallbackHold() override; }; @@ -247,12 +247,12 @@ private: */ void on_active(uint32_t bufferId, uint32_t typeId, size_t entries_needed); - void inc_hold_buffer_count(); + void inc_hold_buffer_count() noexcept; void fallback_resize(uint32_t bufferId, size_t entries_needed); - uint32_t getFirstFreeBufferId(); + uint32_t getFirstFreeBufferId() noexcept; template<typename FuncType> - void for_each_buffer(FuncType func) { + void for_each_buffer(FuncType func) noexcept { uint32_t buffer_id_limit = get_bufferid_limit_relaxed(); for (uint32_t i = 0; i < buffer_id_limit; i++) { func(*(_buffers[i].get_state_relaxed())); diff --git a/vespalib/src/vespa/vespalib/datastore/free_list.cpp b/vespalib/src/vespa/vespalib/datastore/free_list.cpp index d69a23d7883..10e8cf8c030 100644 --- a/vespalib/src/vespa/vespalib/datastore/free_list.cpp +++ b/vespalib/src/vespa/vespalib/datastore/free_list.cpp @@ -6,7 +6,7 @@ namespace vespalib::datastore { -FreeList::FreeList() +FreeList::FreeList() noexcept : _free_lists() { } @@ -23,7 +23,7 @@ FreeList::attach(BufferFreeList& buf_list) } void -FreeList::detach(BufferFreeList& buf_list) +FreeList::detach(BufferFreeList& buf_list) noexcept { if (!_free_lists.empty() && (_free_lists.back() == &buf_list)) { _free_lists.pop_back(); diff --git a/vespalib/src/vespa/vespalib/datastore/free_list.h b/vespalib/src/vespa/vespalib/datastore/free_list.h index 7789d7b8f37..5f1fb2184e7 100644 --- a/vespalib/src/vespa/vespalib/datastore/free_list.h +++ b/vespalib/src/vespa/vespalib/datastore/free_list.h @@ -19,18 +19,18 @@ private: std::vector<BufferFreeList*> _free_lists; public: - FreeList(); + FreeList() noexcept; ~FreeList(); - FreeList(FreeList&&) = default; // Needed for emplace_back() during setup. + FreeList(FreeList&&) noexcept = default; // Needed for emplace_back() during setup. FreeList(const FreeList&) = delete; FreeList& operator=(const FreeList&) = delete; FreeList& operator=(BufferFreeList&&) = delete; void attach(BufferFreeList& buf_list); - void detach(BufferFreeList& buf_list); + void detach(BufferFreeList& buf_list) noexcept; - bool empty() const { return _free_lists.empty(); } - size_t size() const { return _free_lists.size(); } - EntryRef pop_entry() { + bool empty() const noexcept { return _free_lists.empty(); } + size_t size() const noexcept { return _free_lists.size(); } + EntryRef pop_entry() noexcept { return _free_lists.back()->pop_entry(); } }; diff --git a/vespalib/src/vespa/vespalib/datastore/memory_stats.cpp b/vespalib/src/vespa/vespalib/datastore/memory_stats.cpp index f9552904cfb..674af23f46f 100644 --- a/vespalib/src/vespa/vespalib/datastore/memory_stats.cpp +++ b/vespalib/src/vespa/vespalib/datastore/memory_stats.cpp @@ -4,7 +4,7 @@ namespace vespalib::datastore { -MemoryStats::MemoryStats() +MemoryStats::MemoryStats() noexcept : _alloc_entries(0), _used_entries(0), _dead_entries(0), @@ -20,7 +20,7 @@ MemoryStats::MemoryStats() } MemoryStats& -MemoryStats::operator+=(const MemoryStats& rhs) +MemoryStats::operator+=(const MemoryStats& rhs) noexcept { _alloc_entries += rhs._alloc_entries; _used_entries += rhs._used_entries; diff --git a/vespalib/src/vespa/vespalib/datastore/memory_stats.h b/vespalib/src/vespa/vespalib/datastore/memory_stats.h index a5988d00f6b..65066690e8c 100644 --- a/vespalib/src/vespa/vespalib/datastore/memory_stats.h +++ b/vespalib/src/vespa/vespalib/datastore/memory_stats.h @@ -25,8 +25,8 @@ public: uint32_t _activeBuffers; uint32_t _holdBuffers; - MemoryStats(); - MemoryStats& operator+=(const MemoryStats& rhs); + MemoryStats() noexcept; + MemoryStats& operator+=(const MemoryStats& rhs) noexcept; }; } diff --git a/vespalib/src/vespa/vespalib/hwaccelrated/private_helpers.hpp b/vespalib/src/vespa/vespalib/hwaccelrated/private_helpers.hpp index 6731b449462..a53716a2973 100644 --- a/vespalib/src/vespa/vespalib/hwaccelrated/private_helpers.hpp +++ b/vespalib/src/vespa/vespalib/hwaccelrated/private_helpers.hpp @@ -2,6 +2,7 @@ #pragma once +#include <vespa/config.h> #include <vespa/vespalib/util/optimized.h> #include <cstring> @@ -24,6 +25,14 @@ populationCount(const uint64_t *a, size_t sz) { return count; } +#ifdef VESPA_USE_THREAD_SANITIZER +/* + * Source bitvectors might be modified due to feeding during search. + */ +template<typename T, unsigned ChunkSize> +T get(const void * base, bool invert)__attribute__((no_sanitize("thread"))); +#endif + template<typename T, unsigned ChunkSize> T get(const void * base, bool invert) { static_assert(sizeof(T) == ChunkSize, "sizeof(T) == ChunkSize"); diff --git a/vespalib/src/vespa/vespalib/objects/nbostream.h b/vespalib/src/vespa/vespalib/objects/nbostream.h index ab02e7c1f05..f66c261ae91 100644 --- a/vespalib/src/vespa/vespalib/objects/nbostream.h +++ b/vespalib/src/vespa/vespalib/objects/nbostream.h @@ -107,17 +107,13 @@ public: } template <typename T, typename U> - nbostream & - operator<<(const std::pair<T, U> &val) - { + nbostream & operator<<(const std::pair<T, U> &val) { *this << val.first << val.second; return *this; } template <typename T, typename U> - nbostream & - operator>>(std::pair<T, U> &val) - { + nbostream & operator>>(std::pair<T, U> &val) { *this >> val.first >> val.second; return *this; } diff --git a/vespalib/src/vespa/vespalib/util/alloc.h b/vespalib/src/vespa/vespalib/util/alloc.h index e9ae8a0ed58..394deb486aa 100644 --- a/vespalib/src/vespa/vespalib/util/alloc.h +++ b/vespalib/src/vespa/vespalib/util/alloc.h @@ -84,7 +84,7 @@ private: : _alloc(allocator->alloc(sz)), _allocator(allocator) { } - Alloc(const MemoryAllocator * allocator) noexcept + explicit Alloc(const MemoryAllocator * allocator) noexcept : _alloc(), _allocator(allocator) { } @@ -102,19 +102,19 @@ namespace vespalib { /// Rounds up to the closest number that is a power of 2 inline size_t -roundUp2inN(size_t minimum) { +roundUp2inN(size_t minimum) noexcept { return 2ul << Optimized::msbIdx(minimum - 1); } /// Rounds minElems up to the closest number where minElems*elemSize is a power of 2 inline size_t -roundUp2inN(size_t minElems, size_t elemSize) { +roundUp2inN(size_t minElems, size_t elemSize) noexcept { return roundUp2inN(minElems * elemSize)/elemSize; } template <typename T> size_t -roundUp2inN(size_t elems) { +roundUp2inN(size_t elems) noexcept { return roundUp2inN(elems, sizeof(T)); } diff --git a/vespalib/src/vespa/vespalib/util/array.h b/vespalib/src/vespa/vespalib/util/array.h index d0af62861f8..6cc22235361 100644 --- a/vespalib/src/vespa/vespalib/util/array.h +++ b/vespalib/src/vespa/vespalib/util/array.h @@ -83,7 +83,7 @@ public: using value_type = T; using size_type = size_t; - Array(const Alloc & initial=Alloc::alloc()); + Array(const Alloc & initial=Alloc::alloc()) noexcept; Array(size_t sz, const Alloc & initial=Alloc::alloc()); Array(Alloc && buf, size_t sz) noexcept; Array(Array &&rhs) noexcept; diff --git a/vespalib/src/vespa/vespalib/util/array.hpp b/vespalib/src/vespa/vespalib/util/array.hpp index 6ffbd63bd3a..33213df4cf6 100644 --- a/vespalib/src/vespa/vespalib/util/array.hpp +++ b/vespalib/src/vespa/vespalib/util/array.hpp @@ -148,15 +148,15 @@ void Array<T>::increase(size_t n) } template <typename T> -Array<T>::Array(const Alloc & initial) +Array<T>::Array(const Alloc & initial) noexcept : _array(initial.create(0)), _sz(0) { } template <typename T> -Array<T>::Array(Alloc && buf, size_t sz) noexcept : - _array(std::move(buf)), - _sz(sz) +Array<T>::Array(Alloc && buf, size_t sz) noexcept + : _array(std::move(buf)), + _sz(sz) { } @@ -170,25 +170,25 @@ Array<T>::Array(Array &&rhs) noexcept } template <typename T> -Array<T>::Array(size_t sz, const Alloc & initial) : - _array(initial.create(sz * sizeof(T))), - _sz(sz) +Array<T>::Array(size_t sz, const Alloc & initial) + : _array(initial.create(sz * sizeof(T))), + _sz(sz) { construct(array(0), _sz, std::is_trivially_default_constructible<T>()); } template <typename T> -Array<T>::Array(size_t sz, T value, const Alloc & initial) : - _array(initial.create(sz * sizeof(T))), - _sz(sz) +Array<T>::Array(size_t sz, T value, const Alloc & initial) + : _array(initial.create(sz * sizeof(T))), + _sz(sz) { construct(array(0), _sz, value, std::is_trivially_copyable<T>()); } template <typename T> -Array<T>::Array(const_iterator begin_, const_iterator end_, const Alloc & initial) : - _array(initial.create(begin_ != end_ ? sizeof(T) * (end_-begin_) : 0)), - _sz(end_-begin_) +Array<T>::Array(const_iterator begin_, const_iterator end_, const Alloc & initial) + : _array(initial.create(begin_ != end_ ? sizeof(T) * (end_-begin_) : 0)), + _sz(end_-begin_) { construct(array(0), begin_, _sz, std::is_trivially_copyable<T>()); } diff --git a/vespalib/src/vespa/vespalib/util/generation_hold_list.h b/vespalib/src/vespa/vespalib/util/generation_hold_list.h index 5d150c8a015..10ffb38816b 100644 --- a/vespalib/src/vespa/vespalib/util/generation_hold_list.h +++ b/vespalib/src/vespa/vespalib/util/generation_hold_list.h @@ -22,11 +22,11 @@ private: struct ElemWithGen { T elem; generation_t gen; - ElemWithGen(T elem_in, generation_t gen_in) + ElemWithGen(T elem_in, generation_t gen_in) noexcept : elem(std::move(elem_in)), gen(gen_in) {} - size_t byte_size() const { + size_t byte_size() const noexcept { if constexpr (track_bytes_held) { return elem->byte_size(); } @@ -54,7 +54,7 @@ private: void reclaim_internal(generation_t oldest_used_gen, Func callback); public: - GenerationHoldList(); + GenerationHoldList() noexcept; ~GenerationHoldList(); /** @@ -99,7 +99,7 @@ public: template<typename Func> void reclaim_all(Func callback); - size_t get_held_bytes() const { return _held_bytes.load(std::memory_order_relaxed); } + size_t get_held_bytes() const noexcept { return _held_bytes.load(std::memory_order_relaxed); } // Static size of _phase_2_list might depend on std::deque implementation static constexpr size_t sizeof_phase_2_list = sizeof(ElemWithGenList); diff --git a/vespalib/src/vespa/vespalib/util/generation_hold_list.hpp b/vespalib/src/vespa/vespalib/util/generation_hold_list.hpp index 532aa9abe28..dfe84f9cfc0 100644 --- a/vespalib/src/vespa/vespalib/util/generation_hold_list.hpp +++ b/vespalib/src/vespa/vespalib/util/generation_hold_list.hpp @@ -12,7 +12,7 @@ void GenerationHoldList<T, track_bytes_held, use_deque>::assign_generation_internal(generation_t current_gen) { for (auto& elem : _phase_1_list) { - _phase_2_list.push_back(ElemWithGen(std::move(elem), current_gen)); + _phase_2_list.emplace_back(std::move(elem), current_gen); } _phase_1_list.clear(); } @@ -40,7 +40,7 @@ GenerationHoldList<T, track_bytes_held, use_deque>::reclaim_internal(generation_ } template <typename T, bool track_bytes_held, bool use_deque> -GenerationHoldList<T, track_bytes_held, use_deque>::GenerationHoldList() +GenerationHoldList<T, track_bytes_held, use_deque>::GenerationHoldList() noexcept : _phase_1_list(), _phase_2_list(), _held_bytes() diff --git a/vespalib/src/vespa/vespalib/util/generationholder.cpp b/vespalib/src/vespa/vespalib/util/generationholder.cpp index 9930cfedbe4..c172220bac2 100644 --- a/vespalib/src/vespa/vespalib/util/generationholder.cpp +++ b/vespalib/src/vespa/vespalib/util/generationholder.cpp @@ -12,7 +12,7 @@ template void GenerationHolderParent::reclaim_internal GenerationHeldBase::~GenerationHeldBase() = default; -GenerationHolder::GenerationHolder() +GenerationHolder::GenerationHolder() noexcept : GenerationHolderParent() { } diff --git a/vespalib/src/vespa/vespalib/util/generationholder.h b/vespalib/src/vespa/vespalib/util/generationholder.h index 00ce8182394..49ef038ad67 100644 --- a/vespalib/src/vespa/vespalib/util/generationholder.h +++ b/vespalib/src/vespa/vespalib/util/generationholder.h @@ -19,12 +19,12 @@ private: size_t _byte_size; public: - GenerationHeldBase(size_t byte_size_in) + GenerationHeldBase(size_t byte_size_in) noexcept : _byte_size(byte_size_in) { } virtual ~GenerationHeldBase(); - size_t byte_size() const { return _byte_size; } + constexpr size_t byte_size() const noexcept { return _byte_size; } }; using GenerationHolderParent = GenerationHoldList<GenerationHeldBase::UP, true, false>; @@ -35,7 +35,7 @@ using GenerationHolderParent = GenerationHoldList<GenerationHeldBase::UP, true, */ class GenerationHolder : public GenerationHolderParent { public: - GenerationHolder(); + GenerationHolder() noexcept; }; } diff --git a/vespalib/src/vespa/vespalib/util/optimized.h b/vespalib/src/vespa/vespalib/util/optimized.h index 12d1b770904..f651a411367 100644 --- a/vespalib/src/vespa/vespalib/util/optimized.h +++ b/vespalib/src/vespa/vespalib/util/optimized.h @@ -16,15 +16,15 @@ namespace vespalib { class Optimized { public: - static int msbIdx(unsigned int v); - static int msbIdx(unsigned long v); - static int msbIdx(unsigned long long v); - static int lsbIdx(unsigned int v); - static int lsbIdx(unsigned long v); - static int lsbIdx(unsigned long long v); - static constexpr int popCount(unsigned int v) { return __builtin_popcount(v); } - static constexpr int popCount(unsigned long v) { return __builtin_popcountl(v); } - static constexpr int popCount(unsigned long long v) { return __builtin_popcountll(v); } + static int msbIdx(unsigned int v) noexcept; + static int msbIdx(unsigned long v) noexcept; + static int msbIdx(unsigned long long v) noexcept; + static int lsbIdx(unsigned int v) noexcept; + static int lsbIdx(unsigned long v) noexcept; + static int lsbIdx(unsigned long long v) noexcept; + static constexpr int popCount(unsigned int v) noexcept { return __builtin_popcount(v); } + static constexpr int popCount(unsigned long v) noexcept { return __builtin_popcountl(v); } + static constexpr int popCount(unsigned long long v) noexcept { return __builtin_popcountll(v); } }; /** @@ -64,43 +64,43 @@ public: **/ #ifdef __x86_64__ -inline int Optimized::msbIdx(unsigned int v) { +inline int Optimized::msbIdx(unsigned int v) noexcept { unsigned int result; __asm __volatile("bsrl %0,%0" : "=r" (result) : "0" (v)); return result; } -inline int Optimized::lsbIdx(unsigned int v) { +inline int Optimized::lsbIdx(unsigned int v) noexcept { unsigned int result; __asm __volatile("bsfl %0,%0" : "=r" (result) : "0" (v)); return result; } -inline int Optimized::msbIdx(unsigned long v) { +inline int Optimized::msbIdx(unsigned long v) noexcept { unsigned long result; __asm __volatile("bsrq %0,%0" : "=r" (result) : "0" (v)); return result; } -inline int Optimized::lsbIdx(unsigned long v) { +inline int Optimized::lsbIdx(unsigned long v) noexcept { unsigned long result; __asm __volatile("bsfq %0,%0" : "=r" (result) : "0" (v)); return result; } -inline int Optimized::msbIdx(unsigned long long v) { +inline int Optimized::msbIdx(unsigned long long v) noexcept { unsigned long long result; __asm __volatile("bsrq %0,%0" : "=r" (result) : "0" (v)); return result; } -inline int Optimized::lsbIdx(unsigned long long v) { +inline int Optimized::lsbIdx(unsigned long long v) noexcept { unsigned long long result; __asm __volatile("bsfq %0,%0" : "=r" (result) : "0" (v)); return result; } #else -inline int Optimized::msbIdx(unsigned int v) { return v ? sizeof(unsigned int) * 8 - 1 - __builtin_clz(v) : 0; } -inline int Optimized::msbIdx(unsigned long v) { return v ? sizeof(unsigned long) * 8 - 1 - __builtin_clzl(v) : 0; } -inline int Optimized::msbIdx(unsigned long long v) { return v ? sizeof(unsigned long long) * 8 - 1 - __builtin_clzll(v) : 0; } -inline int Optimized::lsbIdx(unsigned int v) { return v ? __builtin_ctz(v) : 0; } -inline int Optimized::lsbIdx(unsigned long v) { return v ? __builtin_ctzl(v) : 0; } -inline int Optimized::lsbIdx(unsigned long long v) { return v ? __builtin_ctzll(v) : 0; } +inline int Optimized::msbIdx(unsigned int v) noexcept { return v ? sizeof(unsigned int) * 8 - 1 - __builtin_clz(v) : 0; } +inline int Optimized::msbIdx(unsigned long v) noexcept { return v ? sizeof(unsigned long) * 8 - 1 - __builtin_clzl(v) : 0; } +inline int Optimized::msbIdx(unsigned long long v) noexcept { return v ? sizeof(unsigned long long) * 8 - 1 - __builtin_clzll(v) : 0; } +inline int Optimized::lsbIdx(unsigned int v) noexcept { return v ? __builtin_ctz(v) : 0; } +inline int Optimized::lsbIdx(unsigned long v) noexcept { return v ? __builtin_ctzl(v) : 0; } +inline int Optimized::lsbIdx(unsigned long long v) noexcept { return v ? __builtin_ctzll(v) : 0; } #endif #define VESPA_DLL_LOCAL __attribute__ ((visibility("hidden"))) diff --git a/vespalib/src/vespa/vespalib/util/rcuvector.h b/vespalib/src/vespa/vespalib/util/rcuvector.h index dcd3fcd8052..7dfe57d4dd0 100644 --- a/vespalib/src/vespa/vespalib/util/rcuvector.h +++ b/vespalib/src/vespa/vespalib/util/rcuvector.h @@ -17,9 +17,8 @@ class RcuVectorHeld : public GenerationHeldBase T _data; public: - RcuVectorHeld(size_t size, T&& data); - - ~RcuVectorHeld(); + RcuVectorHeld(size_t size, T&& data) noexcept; + ~RcuVectorHeld() override; }; @@ -49,11 +48,11 @@ private: GrowStrategy _growStrategy; GenerationHolderType &_genHolder; - size_t calcNewSize(size_t baseSize) const; - size_t calcNewSize() const; + size_t calcNewSize(size_t baseSize) const noexcept; + size_t calcNewSize() const noexcept; void expand(size_t newCapacity); void expandAndInsert(const T & v); - void update_vector_start(); + void update_vector_start() noexcept; protected: virtual void onReallocation(); @@ -80,12 +79,12 @@ public: * isFull() should be called from writer only. * Const type qualifier removed to prevent call from readers. **/ - bool isFull() { return _data.size() == _data.capacity(); } + bool isFull() noexcept { return _data.size() == _data.capacity(); } /** * Return the combined memory usage for this instance. **/ - virtual MemoryUsage getMemoryUsage() const; + virtual MemoryUsage getMemoryUsage() const noexcept; // vector interface // no swap method, use reset() to forget old capacity and holds @@ -106,28 +105,28 @@ public: } } - bool empty() const { return _data.empty(); } + bool empty() const noexcept { return _data.empty(); } /* * size() should be called from writer only. * Const type qualifier removed to prevent call from readers. */ - size_t size() { return _data.size(); } + size_t size() noexcept { return _data.size(); } /* * get_size() should be called from writer only or with proper lock held. * Used in predicate attribute by reader (causing data race). */ - size_t get_size() const { return _data.size(); } + size_t get_size() const noexcept{ return _data.size(); } /* * capacity() should be called from writer only. * Const type qualifier removed to prevent call from readers. */ - size_t capacity() { return _data.capacity(); } + size_t capacity() noexcept { return _data.capacity(); } void clear() { _data.clear(); } /* * operator[]() should be called from writer only. * Overload with const type qualifier removed to prevent call from readers. */ - T & operator[](size_t i) { return _data[i]; } + T & operator[](size_t i) noexcept { return _data[i]; } /* * Readers holding a generation guard can call acquire_elem_ref(i) * to get a const reference to element i. Array bound must be handled @@ -153,7 +152,7 @@ public: }; template <typename T> -class RcuVector : public RcuVectorBase<T> +class RcuVector final : public RcuVectorBase<T> { private: using generation_t = typename RcuVectorBase<T>::generation_t; @@ -173,18 +172,18 @@ public: * New capacity is calculated based on old capacity and grow parameters: * nc = oc + (oc * growPercent / 100) + growDelta. **/ - RcuVector(GrowStrategy growStrategy); - ~RcuVector(); + explicit RcuVector(GrowStrategy growStrategy); + ~RcuVector() override; - generation_t getGeneration() const { return _generation; } - void setGeneration(generation_t generation) { _generation = generation; } + generation_t getGeneration() const noexcept { return _generation; } + void setGeneration(generation_t generation) noexcept { _generation = generation; } /** * Remove all old data vectors where generation < firstUsed. **/ void reclaim_memory(generation_t oldest_used_gen); - MemoryUsage getMemoryUsage() const override; + MemoryUsage getMemoryUsage() const noexcept override; }; } diff --git a/vespalib/src/vespa/vespalib/util/rcuvector.hpp b/vespalib/src/vespa/vespalib/util/rcuvector.hpp index 384c48d2223..07df307e32c 100644 --- a/vespalib/src/vespa/vespalib/util/rcuvector.hpp +++ b/vespalib/src/vespa/vespalib/util/rcuvector.hpp @@ -9,7 +9,7 @@ namespace vespalib { template <typename T> -RcuVectorHeld<T>::RcuVectorHeld(size_t size, T&& data) +RcuVectorHeld<T>::RcuVectorHeld(size_t size, T&& data) noexcept : GenerationHeldBase(size), _data(std::move(data)) { } @@ -18,12 +18,12 @@ template <typename T> RcuVectorHeld<T>::~RcuVectorHeld() = default; template <typename T> -size_t RcuVectorBase<T>::calcNewSize(size_t baseSize) const { +size_t RcuVectorBase<T>::calcNewSize(size_t baseSize) const noexcept { return _growStrategy.calc_new_size(baseSize); } template <typename T> -size_t RcuVectorBase<T>::calcNewSize() const { +size_t RcuVectorBase<T>::calcNewSize() const noexcept { return calcNewSize(_data.capacity()); } @@ -135,7 +135,7 @@ RcuVectorBase<T>::RcuVectorBase(GrowStrategy growStrategy, template <typename T> MemoryUsage -RcuVectorBase<T>::getMemoryUsage() const +RcuVectorBase<T>::getMemoryUsage() const noexcept { MemoryUsage retval; retval.incAllocatedBytes(_data.capacity() * sizeof(T)); @@ -145,7 +145,7 @@ RcuVectorBase<T>::getMemoryUsage() const template <typename T> void -RcuVectorBase<T>::update_vector_start() +RcuVectorBase<T>::update_vector_start() noexcept { _vector_start.store(_data.data(), std::memory_order_release); } @@ -193,7 +193,7 @@ RcuVector<T>::reclaim_memory(generation_t oldest_used_gen) template <typename T> MemoryUsage -RcuVector<T>::getMemoryUsage() const +RcuVector<T>::getMemoryUsage() const noexcept { MemoryUsage retval(RcuVectorBase<T>::getMemoryUsage()); retval.mergeGenerationHeldBytes(_genHolderStore.get_held_bytes()); |