This is an automated email from the ASF dual-hosted git repository. tkalkirill pushed a commit to branch ignite-26594 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit 6c5ea5ff124670be4c8a2d2722ab6817de5afdd3 Author: Kirill Tkalenko <[email protected]> AuthorDate: Fri Oct 3 13:03:32 2025 +0300 IGNITE-26594 wip --- modules/page-memory/build.gradle | 1 + .../persistence/PersistentPageMemory.java | 35 +++---- .../PersistentPageMemoryMetricSource.java | 4 +- .../persistence/PersistentPageMemoryMetrics.java | 75 ++++++++++++++ .../PersistentPageMemoryMetricsTest.java | 114 +++++++++++++++++++++ 5 files changed, 206 insertions(+), 23 deletions(-) diff --git a/modules/page-memory/build.gradle b/modules/page-memory/build.gradle index a20830959e7..7189f055c56 100644 --- a/modules/page-memory/build.gradle +++ b/modules/page-memory/build.gradle @@ -41,6 +41,7 @@ dependencies { testImplementation project(':ignite-failure-handler') testImplementation testFixtures(project(':ignite-core')) testImplementation testFixtures(project(':ignite-configuration')) + testImplementation testFixtures(project(':ignite-metrics')) testImplementation libs.auto.service.annotations testFixturesAnnotationProcessor libs.auto.service diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java index 80741dc7d0f..2c1d0e637a4 100644 --- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java +++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemory.java @@ -82,8 +82,6 @@ import org.apache.ignite.internal.lang.IgniteInternalCheckedException; import org.apache.ignite.internal.lang.IgniteInternalException; import org.apache.ignite.internal.logger.IgniteLogger; import org.apache.ignite.internal.logger.Loggers; -import org.apache.ignite.internal.metrics.IntGauge; -import org.apache.ignite.internal.metrics.LongGauge; import org.apache.ignite.internal.pagememory.FullPageId; import org.apache.ignite.internal.pagememory.PageMemory; import org.apache.ignite.internal.pagememory.configuration.PersistentDataRegionConfiguration; @@ -155,8 +153,6 @@ public class PersistentPageMemory implements PageMemory { /** Data region configuration. */ private final PersistentDataRegionConfiguration dataRegionConfiguration; - private final PersistentPageMemoryMetricSource metricSource; - /** Page IO registry. */ private final PageIoRegistry ioRegistry; @@ -213,6 +209,8 @@ public class PersistentPageMemory implements PageMemory { /** Checkpoint timeout lock. */ private final CheckpointTimeoutLock checkpointTimeoutLock; + private final PersistentPageMemoryMetrics metrics; + /** * Constructor. * @@ -240,8 +238,6 @@ public class PersistentPageMemory implements PageMemory { PartitionDestructionLockManager partitionDestructionLockManager ) { this.dataRegionConfiguration = dataRegionConfiguration; - this.metricSource = metricSource; - initMetrics(); this.ioRegistry = ioRegistry; this.sizes = concat(segmentSizes, checkpointBufferSize); @@ -274,9 +270,15 @@ public class PersistentPageMemory implements PageMemory { throw new IgniteInternalException("Unexpected page replacement mode: " + replacementMode); } + metrics = new PersistentPageMemoryMetrics(metricSource, this, dataRegionConfiguration); + delayedPageReplacementTracker = new DelayedPageReplacementTracker( pageSize, - flushDirtyPageForReplacement, + (pageMemory, fullPageId, buffer) -> { + metrics.incrementWriteToDiskMetric(); + + flushDirtyPageForReplacement.write(pageMemory, fullPageId, buffer); + }, LOG, sizes.length - 1, partitionDestructionLockManager @@ -285,21 +287,6 @@ public class PersistentPageMemory implements PageMemory { this.writeThrottle = null; } - private void initMetrics() { - metricSource.addMetric(new IntGauge( - "UsedCheckpointBufferPages", "Number of currently used pages in checkpoint buffer.", this::usedCheckpointBufferPages - )); - metricSource.addMetric(new IntGauge( - "MaxCheckpointBufferPages", "The capacity of checkpoint buffer in pages.", this::maxCheckpointBufferPages - )); - // TODO: IGNITE-25702 Fix the concept of "region" - metricSource.addMetric(new LongGauge( - "MaxSize", - "Maximum in-memory region size in bytes.", - dataRegionConfiguration::sizeBytes - )); - } - /** * Temporary method to enable throttling in tests. * @@ -850,6 +837,8 @@ public class PersistentPageMemory implements PageMemory { pageStoreManager.read(grpId, pageId, buf, false); actualPageId = getPageId(buf); + + metrics.incrementReadFromDiskMetric(); } finally { rwLock.writeUnlock(lockedPageAbsPtr + PAGE_LOCK_OFFSET, actualPageId == 0 ? TAG_LOCK_ALWAYS : tag(actualPageId)); } @@ -2055,6 +2044,8 @@ public class PersistentPageMemory implements PageMemory { pageStoreWriter.writePage(fullId, buf, partitionGeneration); buf.rewind(); + + metrics.incrementWriteToDiskMetric(); } // We pinned the page either when allocated the temp buffer, or when resolved abs pointer. diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricSource.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricSource.java index 56bcf99c0ab..50f007bd8d6 100644 --- a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricSource.java +++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricSource.java @@ -58,10 +58,12 @@ public class PersistentPageMemoryMetricSource implements MetricSource { /** * Adds metric to the source. */ - public synchronized void addMetric(Metric metric) { + public synchronized <T extends Metric> T addMetric(T metric) { assert !enabled : "Cannot add metrics when source is enabled"; metrics.put(metric.name(), metric); + + return metric; } @Override diff --git a/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetrics.java b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetrics.java new file mode 100644 index 00000000000..c3594ee6cf8 --- /dev/null +++ b/modules/page-memory/src/main/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetrics.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.pagememory.persistence; + +import org.apache.ignite.internal.metrics.IntGauge; +import org.apache.ignite.internal.metrics.LongAdderMetric; +import org.apache.ignite.internal.metrics.LongGauge; +import org.apache.ignite.internal.pagememory.configuration.PersistentDataRegionConfiguration; + +/** Persistent page memory metrics. */ +class PersistentPageMemoryMetrics { + private final LongAdderMetric readPagesFromDisk; + + private final LongAdderMetric writePagesToDisk; + + PersistentPageMemoryMetrics( + PersistentPageMemoryMetricSource source, + PersistentPageMemory pageMemory, + PersistentDataRegionConfiguration dataRegionConfiguration + ) { + source.addMetric(new IntGauge( + "UsedCheckpointBufferPages", + "Number of currently used pages in checkpoint buffer.", + pageMemory::usedCheckpointBufferPages + )); + + source.addMetric(new IntGauge( + "MaxCheckpointBufferPages", + "The capacity of checkpoint buffer in pages.", + pageMemory::maxCheckpointBufferPages + )); + + // TODO: IGNITE-25702 Fix the concept of "region" + source.addMetric(new LongGauge( + "MaxSize", + "Maximum in-memory region size in bytes.", + dataRegionConfiguration::sizeBytes + )); + + readPagesFromDisk = source.addMetric(new LongAdderMetric( + "PagesRead", + "Number of pages read from disk since the last restart." + )); + + writePagesToDisk = source.addMetric(new LongAdderMetric( + "PagesWritten", + "Number of pages written to disk since the last restart." + )); + } + + /** Increases the disk page read metric by one. */ + public void incrementReadFromDiskMetric() { + readPagesFromDisk.increment(); + } + + /** Increases the page writes to disk metric by one. */ + public void incrementWriteToDiskMetric() { + writePagesToDisk.increment(); + } +} diff --git a/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricsTest.java b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricsTest.java new file mode 100644 index 00000000000..e0be64dbe76 --- /dev/null +++ b/modules/page-memory/src/test/java/org/apache/ignite/internal/pagememory/persistence/PersistentPageMemoryMetricsTest.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.pagememory.persistence; + +import static org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.apache.ignite.internal.manager.ComponentContext; +import org.apache.ignite.internal.metrics.Metric; +import org.apache.ignite.internal.metrics.MetricManager; +import org.apache.ignite.internal.metrics.MetricSet; +import org.apache.ignite.internal.metrics.TestMetricManager; +import org.apache.ignite.internal.pagememory.configuration.PersistentDataRegionConfiguration; +import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** For {@link PersistentPageMemoryMetrics} testing. */ +public class PersistentPageMemoryMetricsTest extends BaseIgniteAbstractTest { + private final PersistentPageMemoryMetricSource metricSource = new PersistentPageMemoryMetricSource("test"); + + private final PersistentPageMemory pageMemory = mock(PersistentPageMemory.class); + + private final PersistentDataRegionConfiguration dataRegionConfig = PersistentDataRegionConfiguration.builder().size(100).build(); + + private final PersistentPageMemoryMetrics metrics = new PersistentPageMemoryMetrics(metricSource, pageMemory, dataRegionConfig); + + private final MetricManager metricManager = new TestMetricManager(); + + @BeforeEach + void setUp() { + metricManager.registerSource(metricSource); + metricManager.enable(metricSource); + + assertThat(metricManager.startAsync(new ComponentContext()), willCompleteSuccessfully()); + } + + @AfterEach + void tearDown() { + metricManager.beforeNodeStop(); + + assertThat(metricManager.stopAsync(new ComponentContext()), willCompleteSuccessfully()); + } + + @Test + void testMaxSize() { + checkMetricValue("MaxSize", Long.toString(dataRegionConfig.sizeBytes())); + } + + @Test + void testUsedCheckpointBufferPages() { + when(pageMemory.usedCheckpointBufferPages()).thenReturn(42); + + checkMetricValue("UsedCheckpointBufferPages", "42"); + } + + @Test + void testMaxCheckpointBufferPages() { + when(pageMemory.maxCheckpointBufferPages()).thenReturn(84); + + checkMetricValue("MaxCheckpointBufferPages", "84"); + } + + @Test + void testPagesRead() { + checkMetricValue("PagesRead", "0"); + + metrics.incrementReadFromDiskMetric(); + metrics.incrementReadFromDiskMetric(); + + checkMetricValue("PagesRead", "2"); + } + + @Test + void testPagesWritten() { + checkMetricValue("PagesWritten", "0"); + + metrics.incrementWriteToDiskMetric(); + metrics.incrementWriteToDiskMetric(); + metrics.incrementWriteToDiskMetric(); + + checkMetricValue("PagesWritten", "3"); + } + + private void checkMetricValue(String metricName, String exp) { + MetricSet metricsSet = metricManager.metricSnapshot().metrics().get(metricSource.name()); + + Metric metric = metricsSet.get(metricName); + + assertNotNull(metric, metricName); + + assertEquals(exp, metric.getValueAsString(), metricName); + } +}
