You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by na...@apache.org on 2021/04/15 10:49:55 UTC

[ignite] branch master updated: IGNITE-14385: Add checkpoint information to the performance statistics. (#8928)

This is an automated email from the ASF dual-hosted git repository.

namelchev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 118c64e  IGNITE-14385: Add checkpoint information to the performance statistics. (#8928)
118c64e is described below

commit 118c64e2c9fb8069bbcfbd2bf2b46ac026bb3c7e
Author: Sergei Ryzhov <s....@gmail.com>
AuthorDate: Thu Apr 15 13:49:22 2021 +0300

    IGNITE-14385: Add checkpoint information to the performance statistics. (#8928)
---
 .../org/apache/ignite/internal/IgniteKernal.java   |   2 +-
 .../cache/persistence/DataRegionMetricsImpl.java   |  10 +
 .../IgniteCacheDatabaseSharedManager.java          |   1 +
 .../cache/persistence/checkpoint/Checkpointer.java |  24 +++
 .../FilePerformanceStatisticsReader.java           |  57 ++++++
 .../FilePerformanceStatisticsWriter.java           |  68 ++++++
 .../performancestatistics/OperationType.java       |  18 +-
 .../PerformanceStatisticsHandler.java              |  44 ++++
 .../PerformanceStatisticsProcessor.java            | 117 ++++++++---
 .../db/CheckpointBufferDeadlockTest.java           |  62 +-----
 .../db/SlowCheckpointFileIOFactory.java            |  86 ++++++++
 .../pagemem/BPlusTreePageMemoryImplTest.java       |   7 +-
 .../BPlusTreeReuseListPageMemoryImplTest.java      |   7 +-
 .../IgnitePageMemReplaceDelayedWriteUnitTest.java  |  12 +-
 .../pagemem/IgniteThrottlingUnitTest.java          |  10 +-
 .../pagemem/IndexStoragePageMemoryImplTest.java    |   7 +-
 .../pagemem/PageMemoryImplNoLoadTest.java          |   7 +-
 .../persistence/pagemem/PageMemoryImplTest.java    |   4 +
 .../pagemem/PagesWriteThrottleSmokeTest.java       |  56 +----
 .../processors/database/CacheFreeListSelfTest.java |   9 +-
 .../database/DataRegionMetricsSelfTest.java        |  10 +-
 .../AbstractPerformanceStatisticsTest.java         |  27 +++
 .../performancestatistics/CheckpointTest.java      | 228 +++++++++++++++++++++
 .../IgniteBasicWithPersistenceTestSuite.java       |   4 +-
 24 files changed, 722 insertions(+), 155 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index 6160333..f280ce5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -1251,6 +1251,7 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
 
                 startProcessor(createComponent(IGridClusterStateProcessor.class, ctx));
                 startProcessor(new IgniteAuthenticationProcessor(ctx));
+                startProcessor(new PerformanceStatisticsProcessor(ctx));
                 startProcessor(new GridCacheProcessor(ctx));
                 startProcessor(new IndexProcessor(ctx));
                 startProcessor(new GridQueryProcessor(ctx));
@@ -1268,7 +1269,6 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
                 startProcessor(new DistributedMetaStorageImpl(ctx));
                 startProcessor(new DistributedConfigurationProcessor(ctx));
                 startProcessor(new DurableBackgroundTasksProcessor(ctx));
-                startProcessor(new PerformanceStatisticsProcessor(ctx));
 
                 startTimer.finishGlobalStage("Start processors");
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
index 0be8fd8..7621ea0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/DataRegionMetricsImpl.java
@@ -27,6 +27,7 @@ import org.apache.ignite.internal.processors.metric.MetricRegistry;
 import org.apache.ignite.internal.processors.metric.impl.AtomicLongMetric;
 import org.apache.ignite.internal.processors.metric.impl.HitRateMetric;
 import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.mxbean.MetricsMxBean;
 import org.apache.ignite.spi.metric.Metric;
@@ -110,20 +111,26 @@ public class DataRegionMetricsImpl implements DataRegionMetrics {
     /** */
     private final GridMetricManager mmgr;
 
+    /** Performance statistics processor. */
+    private final PerformanceStatisticsProcessor psproc;
+
     /** Time interval (in milliseconds) when allocations/evictions are counted to calculate rate. */
     private volatile long rateTimeInterval;
 
     /**
      * @param memPlcCfg DataRegionConfiguration.
      * @param mmgr Metrics manager.
+     * @param psproc Performance statistics processor.
      * @param dataRegionMetricsProvider Data region metrics provider.
      */
     public DataRegionMetricsImpl(DataRegionConfiguration memPlcCfg,
         GridMetricManager mmgr,
+        PerformanceStatisticsProcessor psproc,
         DataRegionMetricsProvider dataRegionMetricsProvider) {
         this.memPlcCfg = memPlcCfg;
         this.dataRegionMetricsProvider = dataRegionMetricsProvider;
         this.mmgr = mmgr;
+        this.psproc = psproc;
 
         metricsEnabled = memPlcCfg.isMetricsEnabled();
 
@@ -581,6 +588,9 @@ public class DataRegionMetricsImpl implements DataRegionMetrics {
 
     /** @param time Time to add to {@code totalThrottlingTime} metric in milliseconds. */
     public void addThrottlingTime(long time) {
+        if (psproc.enabled())
+            psproc.pagesWriteThrottle(U.currentTimeMillis(), time);
+
         if (metricsEnabled)
             totalThrottlingTime.add(time);
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
index b6886ac..ceddf8a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/IgniteCacheDatabaseSharedManager.java
@@ -445,6 +445,7 @@ public class IgniteCacheDatabaseSharedManager extends GridCacheSharedManagerAdap
         DataRegionMetricsImpl memMetrics = new DataRegionMetricsImpl(
             dataRegionCfg,
             cctx.kernalContext().metric(),
+            cctx.kernalContext().performanceStatistics(),
             dataRegionMetricsProvider(dataRegionCfg));
 
         DataRegion region = initMemory(dataStorageCfg, dataRegionCfg, memMetrics, trackable, pmPageMgr);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java
index 1ad3160..1424a44 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java
@@ -51,6 +51,7 @@ import org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteCa
 import org.apache.ignite.internal.processors.cache.persistence.snapshot.SnapshotOperation;
 import org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.internal.util.GridConcurrentMultiPairQueue;
 import org.apache.ignite.internal.util.StripedExecutor;
 import org.apache.ignite.internal.util.future.CountDownFuture;
@@ -174,6 +175,9 @@ public class Checkpointer extends GridWorker {
     /** Last checkpoint timestamp. */
     private long lastCpTs;
 
+    /** Performance statistics processor. */
+    private final PerformanceStatisticsProcessor psproc;
+
     /** For testing only. */
     private GridFutureAdapter<Void> enableChangeApplied;
 
@@ -224,6 +228,7 @@ public class Checkpointer extends GridWorker {
         this.checkpointWritePageThreads = Math.max(checkpointWritePageThreads, 1);
         this.checkpointWritePagesPool = initializeCheckpointPool();
         this.cpFreqDeviation = cpFreqDeviation;
+        this.psproc = cacheProcessor.context().kernalContext().performanceStatistics();
 
         scheduledCp = new CheckpointProgressImpl(nextCheckpointInterval());
     }
@@ -597,6 +602,25 @@ public class Checkpointer extends GridWorker {
      * @param tracker Tracker.
      */
     private void updateMetrics(Checkpoint chp, CheckpointMetricsTracker tracker) {
+        if (psproc.enabled()) {
+            psproc.checkpoint(
+                tracker.beforeLockDuration(),
+                tracker.lockWaitDuration(),
+                tracker.listenersExecuteDuration(),
+                tracker.markDuration(),
+                tracker.lockHoldDuration(),
+                tracker.pagesWriteDuration(),
+                tracker.fsyncDuration(),
+                tracker.walCpRecordFsyncDuration(),
+                tracker.writeCheckpointEntryDuration(),
+                tracker.splitAndSortCpPagesDuration(),
+                tracker.totalDuration(),
+                tracker.checkpointStartTime(),
+                chp.pagesSize,
+                tracker.dataPagesWritten(),
+                tracker.cowPagesWritten());
+        }
+
         if (persStoreMetrics.metricsEnabled()) {
             persStoreMetrics.onCheckpoint(
                 tracker.beforeLockDuration(),
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsReader.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsReader.java
index 499ff35..752755f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsReader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsReader.java
@@ -48,7 +48,9 @@ import static java.nio.ByteBuffer.allocateDirect;
 import static java.nio.ByteOrder.nativeOrder;
 import static java.nio.file.Files.walkFileTree;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.CACHE_START;
+import static org.apache.ignite.internal.processors.performancestatistics.OperationType.CHECKPOINT;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.JOB;
+import static org.apache.ignite.internal.processors.performancestatistics.OperationType.PAGES_WRITE_THROTTLE;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.QUERY;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.QUERY_READS;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.TASK;
@@ -56,7 +58,9 @@ import static org.apache.ignite.internal.processors.performancestatistics.Operat
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.cacheOperation;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.cacheRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.cacheStartRecordSize;
+import static org.apache.ignite.internal.processors.performancestatistics.OperationType.checkpointRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.jobRecordSize;
+import static org.apache.ignite.internal.processors.performancestatistics.OperationType.pagesWriteThrottleRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.queryReadsRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.queryRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.taskRecordSize;
@@ -400,6 +404,59 @@ public class FilePerformanceStatisticsReader {
 
             return true;
         }
+        else if (opType == CHECKPOINT) {
+            if (buf.remaining() < checkpointRecordSize())
+                return false;
+
+            long beforeLockDuration = buf.getLong();
+            long lockWaitDuration = buf.getLong();
+            long listenersExecDuration = buf.getLong();
+            long markDuration = buf.getLong();
+            long lockHoldDuration = buf.getLong();
+            long pagesWriteDuration = buf.getLong();
+            long fsyncDuration = buf.getLong();
+            long walCpRecordFsyncDuration = buf.getLong();
+            long writeCheckpointEntryDuration = buf.getLong();
+            long splitAndSortCpPagesDuration = buf.getLong();
+            long totalDuration = buf.getLong();
+            long cpStartTime = buf.getLong();
+            int pagesSize = buf.getInt();
+            int dataPagesWritten = buf.getInt();
+            int cowPagesWritten = buf.getInt();
+
+            for (PerformanceStatisticsHandler handler : curHnd) {
+                handler.checkpoint(nodeId,
+                    beforeLockDuration,
+                    lockWaitDuration,
+                    listenersExecDuration,
+                    markDuration,
+                    lockHoldDuration,
+                    pagesWriteDuration,
+                    fsyncDuration,
+                    walCpRecordFsyncDuration,
+                    writeCheckpointEntryDuration,
+                    splitAndSortCpPagesDuration,
+                    totalDuration,
+                    cpStartTime,
+                    pagesSize,
+                    dataPagesWritten,
+                    cowPagesWritten);
+            }
+
+            return true;
+        }
+        else if (opType == PAGES_WRITE_THROTTLE) {
+            if (buf.remaining() < pagesWriteThrottleRecordSize())
+                return false;
+
+            long endTime = buf.getLong();
+            long duration = buf.getLong();
+
+            for (PerformanceStatisticsHandler handler : curHnd)
+                handler.pagesWriteThrottle(nodeId, endTime, duration);
+
+            return true;
+        }
         else
             throw new IgniteException("Unknown operation type id [typeId=" + opTypeByte + ']');
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsWriter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsWriter.java
index ec90642..405169b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsWriter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/FilePerformanceStatisticsWriter.java
@@ -51,7 +51,9 @@ import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERF_STAT_CACHED_S
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERF_STAT_FILE_MAX_SIZE;
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_PERF_STAT_FLUSH_SIZE;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.CACHE_START;
+import static org.apache.ignite.internal.processors.performancestatistics.OperationType.CHECKPOINT;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.JOB;
+import static org.apache.ignite.internal.processors.performancestatistics.OperationType.PAGES_WRITE_THROTTLE;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.QUERY;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.QUERY_READS;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.TASK;
@@ -59,7 +61,9 @@ import static org.apache.ignite.internal.processors.performancestatistics.Operat
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.TX_ROLLBACK;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.cacheRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.cacheStartRecordSize;
+import static org.apache.ignite.internal.processors.performancestatistics.OperationType.checkpointRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.jobRecordSize;
+import static org.apache.ignite.internal.processors.performancestatistics.OperationType.pagesWriteThrottleRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.queryReadsRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.queryRecordSize;
 import static org.apache.ignite.internal.processors.performancestatistics.OperationType.taskRecordSize;
@@ -318,6 +322,70 @@ public class FilePerformanceStatisticsWriter {
     }
 
     /**
+     * @param beforeLockDuration Before lock duration.
+     * @param lockWaitDuration Lock wait duration.
+     * @param listenersExecDuration Listeners execute duration.
+     * @param markDuration Mark duration.
+     * @param lockHoldDuration Lock hold duration.
+     * @param pagesWriteDuration Pages write duration.
+     * @param fsyncDuration Fsync duration.
+     * @param walCpRecordFsyncDuration Wal cp record fsync duration.
+     * @param writeCpEntryDuration Write checkpoint entry duration.
+     * @param splitAndSortCpPagesDuration Split and sort cp pages duration.
+     * @param totalDuration Total duration in milliseconds.
+     * @param cpStartTime Checkpoint start time in milliseconds.
+     * @param pagesSize Pages size.
+     * @param dataPagesWritten Data pages written.
+     * @param cowPagesWritten Cow pages written.
+     */
+    public void checkpoint(
+        long beforeLockDuration,
+        long lockWaitDuration,
+        long listenersExecDuration,
+        long markDuration,
+        long lockHoldDuration,
+        long pagesWriteDuration,
+        long fsyncDuration,
+        long walCpRecordFsyncDuration,
+        long writeCpEntryDuration,
+        long splitAndSortCpPagesDuration,
+        long totalDuration,
+        long cpStartTime,
+        int pagesSize,
+        int dataPagesWritten,
+        int cowPagesWritten
+    ) {
+        doWrite(CHECKPOINT, checkpointRecordSize(), buf -> {
+            buf.putLong(beforeLockDuration);
+            buf.putLong(lockWaitDuration);
+            buf.putLong(listenersExecDuration);
+            buf.putLong(markDuration);
+            buf.putLong(lockHoldDuration);
+            buf.putLong(pagesWriteDuration);
+            buf.putLong(fsyncDuration);
+            buf.putLong(walCpRecordFsyncDuration);
+            buf.putLong(writeCpEntryDuration);
+            buf.putLong(splitAndSortCpPagesDuration);
+            buf.putLong(totalDuration);
+            buf.putLong(cpStartTime);
+            buf.putInt(pagesSize);
+            buf.putInt(dataPagesWritten);
+            buf.putInt(cowPagesWritten);
+        });
+    }
+
+    /**
+     * @param endTime End time in milliseconds.
+     * @param duration Duration in milliseconds.
+     */
+    public void pagesWriteThrottle(long endTime, long duration) {
+        doWrite(PAGES_WRITE_THROTTLE, pagesWriteThrottleRecordSize(), buf -> {
+            buf.putLong(endTime);
+            buf.putLong(duration);
+        });
+    }
+
+    /**
      * @param op Operation type.
      * @param recSize Record size.
      * @param writer Record writer.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/OperationType.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/OperationType.java
index d287f45..4ee2f6e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/OperationType.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/OperationType.java
@@ -79,7 +79,13 @@ public enum OperationType {
     JOB(16),
 
     /** Cache start. */
-    CACHE_START(17);
+    CACHE_START(17),
+
+    /** Checkpoint. */
+    CHECKPOINT(18),
+
+    /** Pages write throttle. */
+    PAGES_WRITE_THROTTLE(19);
 
     /** Cache operations. */
     public static final EnumSet<OperationType> CACHE_OPS = EnumSet.of(CACHE_GET, CACHE_PUT, CACHE_REMOVE,
@@ -182,4 +188,14 @@ public enum OperationType {
     public static int jobRecordSize() {
         return 24 + 8 + 8 + 8 + 1;
     }
+
+    /** @return Checkpoint record size. */
+    public static int checkpointRecordSize() {
+        return 8 * 12 + 4 * 3;
+    }
+
+    /** @return Pages write throttle record size. */
+    public static int pagesWriteThrottleRecordSize() {
+        return 8 + 8;
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsHandler.java
index 3962db4..0596cfc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsHandler.java
@@ -94,4 +94,48 @@ public interface PerformanceStatisticsHandler {
      * @param timedOut {@code True} if job is timed out.
      */
     void job(UUID nodeId, IgniteUuid sesId, long queuedTime, long startTime, long duration, boolean timedOut);
+
+    /**
+     * @param nodeId Node id.
+     * @param beforeLockDuration Before lock duration.
+     * @param lockWaitDuration Lock wait duration.
+     * @param listenersExecDuration Listeners execute duration.
+     * @param markDuration Mark duration.
+     * @param lockHoldDuration Lock hold duration.
+     * @param pagesWriteDuration Pages write duration.
+     * @param fsyncDuration Fsync duration.
+     * @param walCpRecordFsyncDuration Wal cp record fsync duration.
+     * @param writeCpEntryDuration Write checkpoint entry duration.
+     * @param splitAndSortCpPagesDuration Split and sort cp pages duration.
+     * @param totalDuration Total duration in milliseconds.
+     * @param cpStartTime Checkpoint start time in milliseconds.
+     * @param pagesSize Pages size.
+     * @param dataPagesWritten Data pages written.
+     * @param cowPagesWritten Cow pages written.
+     */
+    void checkpoint(
+        UUID nodeId,
+        long beforeLockDuration,
+        long lockWaitDuration,
+        long listenersExecDuration,
+        long markDuration,
+        long lockHoldDuration,
+        long pagesWriteDuration,
+        long fsyncDuration,
+        long walCpRecordFsyncDuration,
+        long writeCpEntryDuration,
+        long splitAndSortCpPagesDuration,
+        long totalDuration,
+        long cpStartTime,
+        int pagesSize,
+        int dataPagesWritten,
+        int cowPagesWritten
+    );
+
+    /**
+     * @param nodeId Node id.
+     * @param endTime End time in milliseconds.
+     * @param duration Duration in milliseconds.
+     */
+    void pagesWriteThrottle(UUID nodeId, long endTime, long duration);
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsProcessor.java
index ccb5d74..6c53de7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/performancestatistics/PerformanceStatisticsProcessor.java
@@ -70,45 +70,50 @@ public class PerformanceStatisticsProcessor extends GridProcessorAdapter {
     private final ArrayList<PerformanceStatisticsStateListener> lsnrs = new ArrayList<>();
 
     /** Rotate performance statistics process. */
-    private final DistributedProcess<Serializable, Serializable> rotateProc;
+    private DistributedProcess<Serializable, Serializable> rotateProc;
 
     /** @param ctx Kernal context. */
     public PerformanceStatisticsProcessor(GridKernalContext ctx) {
         super(ctx);
 
+        registerStateListener(() -> {
+            if (U.isLocalNodeCoordinator(ctx.discovery()))
+                ctx.cache().cacheDescriptors().values().forEach(desc -> cacheStart(desc.cacheId(), desc.cacheName()));
+        });
+    }
+
+    /** {@inheritDoc} */
+    @Override public void start() throws IgniteCheckedException {
+        super.start();
+
         ctx.internalSubscriptionProcessor().registerDistributedMetastorageListener(
             new DistributedMetastorageLifecycleListener() {
-            @Override public void onReadyForRead(ReadableDistributedMetaStorage metastorage) {
-                metastorage.listen(PERF_STAT_KEY::equals, (key, oldVal, newVal) -> {
-                    // Skip history on local join.
-                    if (!ctx.discovery().localJoinFuture().isDone())
-                        return;
-
-                    onMetastorageUpdate((boolean)newVal);
-                });
-            }
+                @Override public void onReadyForRead(ReadableDistributedMetaStorage metastorage) {
+                    metastorage.listen(PERF_STAT_KEY::equals, (key, oldVal, newVal) -> {
+                        // Skip history on local join.
+                        if (!ctx.discovery().localJoinFuture().isDone())
+                            return;
+
+                        onMetastorageUpdate((boolean)newVal);
+                    });
+                }
 
-            @Override public void onReadyForWrite(DistributedMetaStorage metastorage) {
-                PerformanceStatisticsProcessor.this.metastorage = metastorage;
+                @Override public void onReadyForWrite(DistributedMetaStorage metastorage) {
+                    PerformanceStatisticsProcessor.this.metastorage = metastorage;
 
-                try {
-                    Boolean performanceStatsEnabled = metastorage.read(PERF_STAT_KEY);
+                    try {
+                        Boolean performanceStatsEnabled = metastorage.read(PERF_STAT_KEY);
 
-                    if (performanceStatsEnabled == null)
-                        return;
+                        if (performanceStatsEnabled == null)
+                            return;
 
-                    onMetastorageUpdate(performanceStatsEnabled);
+                        onMetastorageUpdate(performanceStatsEnabled);
+                    }
+                    catch (IgniteCheckedException e) {
+                        throw new IgniteException(e);
+                    }
                 }
-                catch (IgniteCheckedException e) {
-                    throw new IgniteException(e);
-                }
-            }
-        });
-
-        registerStateListener(() -> {
-            if (U.isLocalNodeCoordinator(ctx.discovery()))
-                ctx.cache().cacheDescriptors().values().forEach(desc -> cacheStart(desc.cacheId(), desc.cacheName()));
-        });
+            });
 
         rotateProc = new DistributedProcess<>(ctx, PERFORMANCE_STATISTICS_ROTATE,
             req -> ctx.closure().callLocalSafe(() -> {
@@ -198,6 +203,64 @@ public class PerformanceStatisticsProcessor extends GridProcessorAdapter {
     }
 
     /**
+     * @param beforeLockDuration Before lock duration.
+     * @param lockWaitDuration Lock wait duration.
+     * @param listenersExecDuration Listeners execute duration.
+     * @param markDuration Mark duration.
+     * @param lockHoldDuration Lock hold duration.
+     * @param pagesWriteDuration Pages write duration.
+     * @param fsyncDuration Fsync duration.
+     * @param walCpRecordFsyncDuration Wal cp record fsync duration.
+     * @param writeCpEntryDuration Write checkpoint entry duration.
+     * @param splitAndSortCpPagesDuration Split and sort cp pages duration.
+     * @param totalDuration Total duration in milliseconds.
+     * @param cpStartTime Checkpoint start time in milliseconds.
+     * @param pagesSize Pages size.
+     * @param dataPagesWritten Data pages written.
+     * @param cowPagesWritten Cow pages written.
+     */
+    public void checkpoint(
+        long beforeLockDuration,
+        long lockWaitDuration,
+        long listenersExecDuration,
+        long markDuration,
+        long lockHoldDuration,
+        long pagesWriteDuration,
+        long fsyncDuration,
+        long walCpRecordFsyncDuration,
+        long writeCpEntryDuration,
+        long splitAndSortCpPagesDuration,
+        long totalDuration,
+        long cpStartTime,
+        int pagesSize,
+        int dataPagesWritten,
+        int cowPagesWritten
+    ) {
+        write(writer -> writer.checkpoint(beforeLockDuration,
+            lockWaitDuration,
+            listenersExecDuration,
+            markDuration,
+            lockHoldDuration,
+            pagesWriteDuration, fsyncDuration,
+            walCpRecordFsyncDuration,
+            writeCpEntryDuration,
+            splitAndSortCpPagesDuration,
+            totalDuration,
+            cpStartTime,
+            pagesSize,
+            dataPagesWritten,
+            cowPagesWritten));
+    }
+
+    /**
+     * @param endTime End time in milliseconds.
+     * @param duration Duration in milliseconds.
+     */
+    public void pagesWriteThrottle(long endTime, long duration) {
+        write(writer -> writer.pagesWriteThrottle(endTime, duration));
+    }
+
+    /**
      * Starts collecting performance statistics.
      *
      * @throws IgniteCheckedException If starting failed.
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/CheckpointBufferDeadlockTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/CheckpointBufferDeadlockTest.java
index ca808ad..abe182b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/CheckpointBufferDeadlockTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/CheckpointBufferDeadlockTest.java
@@ -16,11 +16,6 @@
 */
 package org.apache.ignite.internal.processors.cache.persistence.db;
 
-import java.io.File;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
-import java.nio.file.OpenOption;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashSet;
@@ -28,7 +23,6 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.LockSupport;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
@@ -45,11 +39,7 @@ import org.apache.ignite.internal.pagemem.PageIdUtils;
 import org.apache.ignite.internal.pagemem.store.PageStore;
 import org.apache.ignite.internal.processors.cache.persistence.DataRegion;
 import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
-import org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
-import org.apache.ignite.internal.processors.cache.persistence.file.FileIODecorator;
-import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
 import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager;
-import org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIOFactory;
 import org.apache.ignite.internal.processors.cache.persistence.pagemem.PageMemoryImpl;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.util.typedef.internal.CU;
@@ -98,7 +88,7 @@ public class CheckpointBufferDeadlockTest extends GridCommonAbstractTest {
 
         cfg.setDataStorageConfiguration(
             new DataStorageConfiguration()
-                .setFileIOFactory(new SlowCheckpointFileIOFactory())
+                .setFileIOFactory(new SlowCheckpointFileIOFactory(slowCheckpointEnabled, CHECKPOINT_PARK_NANOS))
                 .setCheckpointThreads(checkpointThreads)
                 .setDefaultDataRegionConfiguration(
                     new DataRegionConfiguration()
@@ -342,54 +332,4 @@ public class CheckpointBufferDeadlockTest extends GridCommonAbstractTest {
 
         log.unregisterListener(lsnr);
     }
-
-    /**
-     * Create File I/O that emulates poor checkpoint write speed.
-     */
-    private static class SlowCheckpointFileIOFactory implements FileIOFactory {
-        /** Serial version uid. */
-        private static final long serialVersionUID = 0L;
-
-        /** Delegate factory. */
-        private final FileIOFactory delegateFactory = new RandomAccessFileIOFactory();
-
-        /** {@inheritDoc} */
-        @Override public FileIO create(File file, OpenOption... openOption) throws IOException {
-            final FileIO delegate = delegateFactory.create(file, openOption);
-
-            return new FileIODecorator(delegate) {
-                @Override public int write(ByteBuffer srcBuf) throws IOException {
-                    parkIfNeeded();
-
-                    return delegate.write(srcBuf);
-                }
-
-                @Override public int write(ByteBuffer srcBuf, long position) throws IOException {
-                    parkIfNeeded();
-
-                    return delegate.write(srcBuf, position);
-                }
-
-                @Override public int write(byte[] buf, int off, int len) throws IOException {
-                    parkIfNeeded();
-
-                    return delegate.write(buf, off, len);
-                }
-
-                /**
-                 * Parks current checkpoint thread if slow mode is enabled.
-                 */
-                private void parkIfNeeded() {
-                    if (slowCheckpointEnabled.get() && Thread.currentThread().getName().contains("checkpoint"))
-                        LockSupport.parkNanos(CHECKPOINT_PARK_NANOS);
-                }
-
-                /** {@inheritDoc} */
-                @Override public MappedByteBuffer map(int sizeBytes) throws IOException {
-                    return delegate.map(sizeBytes);
-                }
-            };
-        }
-    }
-
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/SlowCheckpointFileIOFactory.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/SlowCheckpointFileIOFactory.java
new file mode 100644
index 0000000..cad6b56
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/db/SlowCheckpointFileIOFactory.java
@@ -0,0 +1,86 @@
+/*
+ * 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.processors.cache.persistence.db;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.OpenOption;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.LockSupport;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIODecorator;
+import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
+import org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIOFactory;
+
+/**
+ * Create File I/O that emulates poor checkpoint write speed.
+ */
+public class SlowCheckpointFileIOFactory implements FileIOFactory {
+    /** Serial version uid. */
+    private static final long serialVersionUID = 0L;
+
+    /** Delegate factory. */
+    private final FileIOFactory delegateFactory = new RandomAccessFileIOFactory();
+
+    /** Slow checkpoint enabled. */
+    private final AtomicBoolean slowCheckpointEnabled;
+
+    /** Checkpoint park nanos. */
+    private final int checkpointParkNanos;
+
+    /**
+     * @param slowCheckpointEnabled Slow checkpoint enabled.
+     * @param checkpointParkNanos Checkpoint park nanos.
+     */
+    public SlowCheckpointFileIOFactory(AtomicBoolean slowCheckpointEnabled, int checkpointParkNanos) {
+        this.slowCheckpointEnabled = slowCheckpointEnabled;
+        this.checkpointParkNanos = checkpointParkNanos;
+    }
+
+    /** {@inheritDoc} */
+    @Override public FileIO create(File file, OpenOption... openOption) throws IOException {
+        final FileIO delegate = delegateFactory.create(file, openOption);
+
+        return new FileIODecorator(delegate) {
+            @Override public int write(ByteBuffer srcBuf) throws IOException {
+                parkIfNeeded();
+
+                return delegate.write(srcBuf);
+            }
+
+            @Override public int write(ByteBuffer srcBuf, long position) throws IOException {
+                parkIfNeeded();
+
+                return delegate.write(srcBuf, position);
+            }
+
+            @Override public int write(byte[] buf, int off, int len) throws IOException {
+                parkIfNeeded();
+
+                return delegate.write(buf, off, len);
+            }
+
+            /** Parks current checkpoint thread if slow mode is enabled. */
+            private void parkIfNeeded() {
+                if (slowCheckpointEnabled.get() && Thread.currentThread().getName().contains("db-checkpoint-thread"))
+                    LockSupport.parkNanos(checkpointParkNanos);
+            }
+        };
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
index 33ae0cf..c44a903 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreePageMemoryImplTest.java
@@ -36,6 +36,7 @@ import org.apache.ignite.internal.processors.cache.persistence.checkpoint.Checkp
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgressImpl;
 import org.apache.ignite.internal.processors.database.BPlusTreeSelfTest;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
 import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
 import org.apache.ignite.internal.util.typedef.CIX3;
@@ -73,6 +74,7 @@ public class BPlusTreePageMemoryImplTest extends BPlusTreeSelfTest {
 
         cctx.add(new IgnitePluginProcessor(cctx, cfg, Collections.emptyList()));
         cctx.add(new GridInternalSubscriptionProcessor(cctx));
+        cctx.add(new PerformanceStatisticsProcessor(cctx));
         cctx.add(new GridEncryptionManager(cctx));
         cctx.add(new GridMetricManager(cctx));
         cctx.add(new GridSystemViewManager(cctx));
@@ -120,7 +122,10 @@ public class BPlusTreePageMemoryImplTest extends BPlusTreeSelfTest {
                 }
             },
             () -> true,
-            new DataRegionMetricsImpl(new DataRegionConfiguration(), cctx.metric(), NO_OP_METRICS),
+            new DataRegionMetricsImpl(new DataRegionConfiguration(),
+                cctx.metric(),
+                cctx.performanceStatistics(),
+                NO_OP_METRICS),
             PageMemoryImpl.ThrottlingPolicy.DISABLED,
             clo
         );
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
index 3c37874..024b2ad 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/BPlusTreeReuseListPageMemoryImplTest.java
@@ -35,6 +35,7 @@ import org.apache.ignite.internal.processors.cache.persistence.checkpoint.Checkp
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgressImpl;
 import org.apache.ignite.internal.processors.database.BPlusTreeReuseSelfTest;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
 import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
 import org.apache.ignite.internal.util.lang.GridInClosure3X;
@@ -72,6 +73,7 @@ public class BPlusTreeReuseListPageMemoryImplTest extends BPlusTreeReuseSelfTest
 
         cctx.add(new IgnitePluginProcessor(cctx, cfg, Collections.emptyList()));
         cctx.add(new GridInternalSubscriptionProcessor(cctx));
+        cctx.add(new PerformanceStatisticsProcessor(cctx));
         cctx.add(new GridEncryptionManager(cctx));
         cctx.add(new GridMetricManager(cctx));
         cctx.add(new GridSystemViewManager(cctx));
@@ -119,7 +121,10 @@ public class BPlusTreeReuseListPageMemoryImplTest extends BPlusTreeReuseSelfTest
                 }
             },
             () -> true,
-            new DataRegionMetricsImpl(new DataRegionConfiguration(), cctx.metric(), NO_OP_METRICS),
+            new DataRegionMetricsImpl(new DataRegionConfiguration(),
+                cctx.metric(),
+                cctx.performanceStatistics(),
+                NO_OP_METRICS),
             PageMemoryImpl.ThrottlingPolicy.DISABLED,
             clo
         );
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java
index 1f6d5ce..362044f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgnitePageMemReplaceDelayedWriteUnitTest.java
@@ -45,6 +45,7 @@ import org.apache.ignite.internal.processors.cache.persistence.PageStoreWriter;
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgress;
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgressImpl;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
 import org.apache.ignite.internal.util.GridMultiCollectionWrapper;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
@@ -253,6 +254,12 @@ public class IgnitePageMemReplaceDelayedWriteUnitTest {
             }
         });
 
+        when(kernalCtx.performanceStatistics()).thenAnswer(new Answer<Object>() {
+            @Override public Object answer(InvocationOnMock mock) throws Throwable {
+                return new PerformanceStatisticsProcessor(kernalCtx);
+            }
+        });
+
         when(sctx.kernalContext()).thenReturn(kernalCtx);
 
         when(sctx.gridEvents()).thenAnswer(new Answer<Object>() {
@@ -263,7 +270,10 @@ public class IgnitePageMemReplaceDelayedWriteUnitTest {
 
         DataRegionConfiguration regCfg = cfg.getDataStorageConfiguration().getDefaultDataRegionConfiguration();
 
-        DataRegionMetricsImpl memMetrics = new DataRegionMetricsImpl(regCfg, kernalCtx.metric(), NO_OP_METRICS);
+        DataRegionMetricsImpl memMetrics = new DataRegionMetricsImpl(regCfg,
+            kernalCtx.metric(),
+            kernalCtx.performanceStatistics(),
+            NO_OP_METRICS);
 
         long[] sizes = prepareSegmentSizes(regCfg.getMaxSize());
 
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgniteThrottlingUnitTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgniteThrottlingUnitTest.java
index 35d98f8..2fcb627 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgniteThrottlingUnitTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IgniteThrottlingUnitTest.java
@@ -32,6 +32,7 @@ import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetrics
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgress;
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgressImpl;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.lang.IgniteOutClosure;
 import org.apache.ignite.logger.NullLogger;
 import org.apache.ignite.spi.metric.noop.NoopMetricExporterSpi;
@@ -76,8 +77,15 @@ public class IgniteThrottlingUnitTest {
 
         IgniteConfiguration cfg = new IgniteConfiguration().setMetricExporterSpi(new NoopMetricExporterSpi());
 
+        GridTestKernalContext ctx = new GridTestKernalContext(new GridTestLog4jLogger(), cfg);
+
+        ctx.add(new GridMetricManager(ctx));
+        ctx.add(new PerformanceStatisticsProcessor(ctx));
+
         DataRegionMetricsImpl metrics = new DataRegionMetricsImpl(new DataRegionConfiguration(),
-            new GridMetricManager(new GridTestKernalContext(new GridTestLog4jLogger(), cfg)), NO_OP_METRICS);
+            ctx.metric(),
+            ctx.performanceStatistics(),
+            NO_OP_METRICS);
 
         when(pageMemory2g.metrics()).thenReturn(metrics);
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
index fa89f05..eb22cce 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/IndexStoragePageMemoryImplTest.java
@@ -37,6 +37,7 @@ import org.apache.ignite.internal.processors.cache.persistence.checkpoint.Checkp
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgressImpl;
 import org.apache.ignite.internal.processors.database.IndexStorageSelfTest;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
 import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
 import org.apache.ignite.internal.util.lang.GridInClosure3X;
@@ -88,6 +89,7 @@ public class IndexStoragePageMemoryImplTest extends IndexStorageSelfTest {
 
         cctx.add(new IgnitePluginProcessor(cctx, cfg, Collections.emptyList()));
         cctx.add(new GridInternalSubscriptionProcessor(cctx));
+        cctx.add(new PerformanceStatisticsProcessor(cctx));
         cctx.add(new GridEncryptionManager(cctx));
         cctx.add(new GridMetricManager(cctx));
         cctx.add(new GridSystemViewManager(cctx));
@@ -135,7 +137,10 @@ public class IndexStoragePageMemoryImplTest extends IndexStorageSelfTest {
                 }
             },
             () -> true,
-            new DataRegionMetricsImpl(new DataRegionConfiguration(), cctx.metric(), NO_OP_METRICS),
+            new DataRegionMetricsImpl(new DataRegionConfiguration(),
+                cctx.metric(),
+                cctx.performanceStatistics(),
+                NO_OP_METRICS),
             PageMemoryImpl.ThrottlingPolicy.DISABLED,
             clo
         );
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
index 149086b..6edd85a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplNoLoadTest.java
@@ -37,6 +37,7 @@ import org.apache.ignite.internal.processors.cache.persistence.IgniteCacheDataba
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgress;
 import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointProgressImpl;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
 import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
 import org.apache.ignite.internal.util.lang.GridInClosure3X;
@@ -78,6 +79,7 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
 
         cctx.add(new IgnitePluginProcessor(cctx, cfg, Collections.emptyList()));
         cctx.add(new GridInternalSubscriptionProcessor(cctx));
+        cctx.add(new PerformanceStatisticsProcessor(cctx));
         cctx.add(new GridEncryptionManager(cctx));
         cctx.add(new GridMetricManager(cctx));
         cctx.add(new GridSystemViewManager(cctx));
@@ -130,7 +132,10 @@ public class PageMemoryImplNoLoadTest extends PageMemoryNoLoadSelfTest {
                     return true;
                 }
             },
-            new DataRegionMetricsImpl(new DataRegionConfiguration(), cctx.metric(), NO_OP_METRICS),
+            new DataRegionMetricsImpl(new DataRegionConfiguration(),
+                cctx.metric(),
+                cctx.performanceStatistics(),
+                NO_OP_METRICS),
             PageMemoryImpl.ThrottlingPolicy.DISABLED,
             clo
         );
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
index d271fce..90aba97 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImplTest.java
@@ -56,6 +56,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.processors.failure.FailureProcessor;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
 import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.internal.processors.plugin.IgnitePluginProcessor;
 import org.apache.ignite.internal.processors.subscription.GridInternalSubscriptionProcessor;
 import org.apache.ignite.internal.util.GridMultiCollectionWrapper;
@@ -594,6 +595,7 @@ public class PageMemoryImplTest extends GridCommonAbstractTest {
 
         kernalCtx.add(new IgnitePluginProcessor(kernalCtx, igniteCfg, Collections.<PluginProvider>emptyList()));
         kernalCtx.add(new GridInternalSubscriptionProcessor(kernalCtx));
+        kernalCtx.add(new PerformanceStatisticsProcessor(kernalCtx));
         kernalCtx.add(new GridEncryptionManager(kernalCtx));
         kernalCtx.add(new GridMetricManager(kernalCtx));
         kernalCtx.add(new GridSystemViewManager(kernalCtx));
@@ -656,6 +658,7 @@ public class PageMemoryImplTest extends GridCommonAbstractTest {
             },
             new DataRegionMetricsImpl(igniteCfg.getDataStorageConfiguration().getDefaultDataRegionConfiguration(),
                 kernalCtx.metric(),
+                kernalCtx.performanceStatistics(),
                 NO_OP_METRICS),
             throttlingPlc,
             noThrottle
@@ -676,6 +679,7 @@ public class PageMemoryImplTest extends GridCommonAbstractTest {
         },
             new DataRegionMetricsImpl(igniteCfg.getDataStorageConfiguration().getDefaultDataRegionConfiguration(),
                 kernalCtx.metric(),
+                kernalCtx.performanceStatistics(),
                 NO_OP_METRICS),
             throttlingPlc,
             noThrottle
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PagesWriteThrottleSmokeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PagesWriteThrottleSmokeTest.java
index 796db43..4a20d18 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PagesWriteThrottleSmokeTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PagesWriteThrottleSmokeTest.java
@@ -16,12 +16,7 @@
 */
 package org.apache.ignite.internal.processors.cache.persistence.pagemem;
 
-import java.io.File;
-import java.io.IOException;
 import java.io.Serializable;
-import java.nio.ByteBuffer;
-import java.nio.MappedByteBuffer;
-import java.nio.file.OpenOption;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.LockSupport;
@@ -36,10 +31,7 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.WALMode;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.processors.cache.persistence.file.FileIO;
-import org.apache.ignite.internal.processors.cache.persistence.file.FileIODecorator;
-import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory;
-import org.apache.ignite.internal.processors.cache.persistence.file.RandomAccessFileIOFactory;
+import org.apache.ignite.internal.processors.cache.persistence.db.SlowCheckpointFileIOFactory;
 import org.apache.ignite.internal.processors.metric.MetricRegistry;
 import org.apache.ignite.internal.processors.metric.impl.HitRateMetric;
 import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric;
@@ -77,7 +69,7 @@ public class PagesWriteThrottleSmokeTest extends GridCommonAbstractTest {
             .setCheckpointFrequency(20_000)
             .setWriteThrottlingEnabled(true)
             .setCheckpointThreads(1)
-            .setFileIOFactory(new SlowCheckpointFileIOFactory());
+            .setFileIOFactory(new SlowCheckpointFileIOFactory(slowCheckpointEnabled, 5_000_000));
 
         cfg.setDataStorageConfiguration(dbCfg);
 
@@ -288,48 +280,4 @@ public class PagesWriteThrottleSmokeTest extends GridCommonAbstractTest {
 
         U.delete(U.resolveWorkDirectory(U.defaultWorkDirectory(), "snapshot", false));
     }
-
-    /**
-     * Create File I/O that emulates poor checkpoint write speed.
-     */
-    private static class SlowCheckpointFileIOFactory implements FileIOFactory {
-        /** Serial version uid. */
-        private static final long serialVersionUID = 0L;
-
-        /** Delegate factory. */
-        private final FileIOFactory delegateFactory = new RandomAccessFileIOFactory();
-
-        /** {@inheritDoc} */
-        @Override public FileIO create(File file, OpenOption... openOption) throws IOException {
-            final FileIO delegate = delegateFactory.create(file, openOption);
-
-            return new FileIODecorator(delegate) {
-                @Override public int write(ByteBuffer srcBuf) throws IOException {
-                    if (slowCheckpointEnabled.get() && Thread.currentThread().getName().contains("checkpoint"))
-                        LockSupport.parkNanos(5_000_000);
-
-                    return delegate.write(srcBuf);
-                }
-
-                @Override public int write(ByteBuffer srcBuf, long position) throws IOException {
-                    if (slowCheckpointEnabled.get() && Thread.currentThread().getName().contains("checkpoint"))
-                        LockSupport.parkNanos(5_000_000);
-
-                    return delegate.write(srcBuf, position);
-                }
-
-                @Override public int write(byte[] buf, int off, int len) throws IOException {
-                    if (slowCheckpointEnabled.get() && Thread.currentThread().getName().contains("checkpoint"))
-                        LockSupport.parkNanos(5_000_000);
-
-                    return delegate.write(buf, off, len);
-                }
-
-                /** {@inheritDoc} */
-                @Override public MappedByteBuffer map(int sizeBytes) throws IOException {
-                    return delegate.map(sizeBytes);
-                }
-            };
-        }
-    }
 }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
index 1c0f33d..82c54f7 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/CacheFreeListSelfTest.java
@@ -53,6 +53,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.io.CacheVers
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
 import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
 import org.apache.ignite.spi.metric.noop.NoopMetricExporterSpi;
@@ -514,8 +515,14 @@ public class CacheFreeListSelfTest extends GridCommonAbstractTest {
 
         IgniteConfiguration cfg = new IgniteConfiguration().setMetricExporterSpi(new NoopMetricExporterSpi());
 
+        GridTestKernalContext ctx = new GridTestKernalContext(new GridTestLog4jLogger(), cfg);
+
+        ctx.add(new GridMetricManager(ctx));
+        ctx.add(new PerformanceStatisticsProcessor(ctx));
+
         DataRegionMetricsImpl regionMetrics = new DataRegionMetricsImpl(plcCfg,
-            new GridMetricManager(new GridTestKernalContext(new GridTestLog4jLogger(), cfg)),
+            ctx.metric(),
+            ctx.performanceStatistics(),
             NO_OP_METRICS);
 
         DataRegion dataRegion = new DataRegion(pageMem, plcCfg, regionMetrics, new NoOpPageEvictionTracker());
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/DataRegionMetricsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/DataRegionMetricsSelfTest.java
index 3bf92c2..0d6c25d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/database/DataRegionMetricsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/database/DataRegionMetricsSelfTest.java
@@ -25,6 +25,7 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl;
 import org.apache.ignite.internal.processors.metric.GridMetricManager;
 import org.apache.ignite.internal.processors.metric.impl.HitRateMetric;
+import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsProcessor;
 import org.apache.ignite.spi.metric.noop.NoopMetricExporterSpi;
 import org.apache.ignite.testframework.junits.GridTestKernalContext;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
@@ -74,9 +75,12 @@ public class DataRegionMetricsSelfTest extends GridCommonAbstractTest {
 
         IgniteConfiguration cfg = new IgniteConfiguration().setMetricExporterSpi(new NoopMetricExporterSpi());
 
-        memMetrics = new DataRegionMetricsImpl(plcCfg,
-            new GridMetricManager(new GridTestKernalContext(new GridTestLog4jLogger(), cfg)),
-            NO_OP_METRICS);
+        GridTestKernalContext ctx = new GridTestKernalContext(new GridTestLog4jLogger(), cfg);
+
+        ctx.add(new GridMetricManager(ctx));
+        ctx.add(new PerformanceStatisticsProcessor(ctx));
+
+        memMetrics = new DataRegionMetricsImpl(plcCfg, ctx.metric(), ctx.performanceStatistics(), NO_OP_METRICS);
 
         memMetrics.enableMetrics();
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/AbstractPerformanceStatisticsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/AbstractPerformanceStatisticsTest.java
index 6867974..779f15a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/AbstractPerformanceStatisticsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/AbstractPerformanceStatisticsTest.java
@@ -197,6 +197,33 @@ public abstract class AbstractPerformanceStatisticsTest extends GridCommonAbstra
             boolean timedOut) {
             // No-op.
         }
+
+        /** {@inheritDoc} */
+        @Override public void checkpoint(
+            UUID nodeId,
+            long beforeLockDuration,
+            long lockWaitDuration,
+            long listenersExecDuration,
+            long markDuration,
+            long lockHoldDuration,
+            long pagesWriteDuration,
+            long fsyncDuration,
+            long walCpRecordFsyncDuration,
+            long writeCpEntryDuration,
+            long splitAndSortCpPagesDuration,
+            long totalDuration,
+            long cpStartTime,
+            int pagesSize,
+            int dataPagesWritten,
+            int cowPagesWritten
+        ) {
+            // No-op.
+        }
+
+        /** {@inheritDoc} */
+        @Override public void pagesWriteThrottle(UUID nodeId, long endTime, long duration) {
+            // No-op.
+        }
     }
 
     /** Client type to run load from. */
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/CheckpointTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/CheckpointTest.java
new file mode 100644
index 0000000..386738d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/performancestatistics/CheckpointTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.processors.performancestatistics;
+
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cluster.ClusterState;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.cache.persistence.db.SlowCheckpointFileIOFactory;
+import org.apache.ignite.internal.processors.metric.MetricRegistry;
+import org.apache.ignite.internal.processors.metric.impl.LongAdderMetric;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.metric.LongMetric;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.WithSystemProperty;
+import org.junit.Test;
+
+import static org.apache.ignite.IgniteSystemProperties.IGNITE_OVERRIDE_WRITE_THROTTLING_ENABLED;
+import static org.apache.ignite.configuration.DataStorageConfiguration.DFLT_DATA_REG_DEFAULT_NAME;
+import static org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl.DATAREGION_METRICS_PREFIX;
+import static org.apache.ignite.internal.processors.cache.persistence.DataStorageMetricsImpl.DATASTORAGE_METRIC_PREFIX;
+import static org.apache.ignite.internal.processors.metric.impl.MetricUtils.metricName;
+import static org.apache.ignite.testframework.GridTestUtils.waitForCondition;
+
+/**
+ * Tests checkpoint performance statistics.
+ */
+public class CheckpointTest extends AbstractPerformanceStatisticsTest {
+    /** Slow checkpoint enabled. */
+    private static final AtomicBoolean slowCheckpointEnabled = new AtomicBoolean(false);
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setCacheConfiguration(defaultCacheConfiguration());
+        cfg.setDataStorageConfiguration(new DataStorageConfiguration()
+            .setMetricsEnabled(true)
+            .setDefaultDataRegionConfiguration(new DataRegionConfiguration()
+                .setMaxSize(10 * 1024 * 1024)
+                .setCheckpointPageBufferSize(1024 * 1024)
+                .setMetricsEnabled(true)
+                .setPersistenceEnabled(true))
+            .setWriteThrottlingEnabled(true)
+            .setFileIOFactory(new SlowCheckpointFileIOFactory(slowCheckpointEnabled, 500_000))
+            .setCheckpointThreads(1));
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        cleanPersistenceDir();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        slowCheckpointEnabled.set(false);
+
+        stopAllGrids();
+
+        cleanPersistenceDir();
+    }
+
+    /** @throws Exception If failed. */
+    @Test
+    public void testCheckpoint() throws Exception {
+        IgniteEx srv = startGrid();
+
+        srv.cluster().state(ClusterState.ACTIVE);
+
+        MetricRegistry mreg = srv.context().metric().registry(DATASTORAGE_METRIC_PREFIX);
+
+        LongMetric lastStart = mreg.findMetric("LastCheckpointStart");
+
+        // Wait for checkpoint to finish on node start.
+        assertTrue(waitForCondition(() -> 0 < lastStart.value(), TIMEOUT));
+
+        lastStart.reset();
+
+        startCollectStatistics();
+
+        forceCheckpoint();
+
+        assertTrue(waitForCondition(() -> 0 < lastStart.value(), TIMEOUT));
+
+        AtomicInteger cnt = new AtomicInteger();
+
+        stopCollectStatisticsAndRead(new TestHandler() {
+            @Override public void checkpoint(
+                UUID nodeId,
+                long beforeLockDuration,
+                long lockWaitDuration,
+                long listenersExecDuration,
+                long markDuration,
+                long lockHoldDuration,
+                long pagesWriteDuration,
+                long fsyncDuration,
+                long walCpRecordFsyncDuration,
+                long writeCpEntryDuration,
+                long splitAndSortCpPagesDuration,
+                long totalDuration,
+                long cpStartTime,
+                int pagesSize,
+                int dataPagesWritten,
+                int cowPagesWritten
+            ) {
+                assertEquals(srv.localNode().id(), nodeId);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointBeforeLockDuration").value(),
+                    beforeLockDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointLockWaitDuration").value(),
+                    lockWaitDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointListenersExecuteDuration").value(),
+                    listenersExecDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointMarkDuration").value(), markDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointLockHoldDuration").value(),
+                    lockHoldDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointPagesWriteDuration").value(),
+                    pagesWriteDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointFsyncDuration").value(), fsyncDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointWalRecordFsyncDuration").value(),
+                    walCpRecordFsyncDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointWriteEntryDuration").value(),
+                    writeCpEntryDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointSplitAndSortPagesDuration").value(),
+                    splitAndSortCpPagesDuration);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointDuration").value(), totalDuration);
+                assertEquals(lastStart.value(), cpStartTime);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointTotalPagesNumber").value(), pagesSize);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointDataPagesNumber").value(),
+                    dataPagesWritten);
+                assertEquals(mreg.<LongMetric>findMetric("LastCheckpointCopiedOnWritePagesNumber").value(),
+                    cowPagesWritten);
+
+                cnt.incrementAndGet();
+            }
+        });
+
+        assertEquals(1, cnt.get());
+    }
+
+    /** @throws Exception if failed. */
+    @Test
+    public void testThrottleSpeedBased() throws Exception {
+        checkThrottling();
+    }
+
+    /** @throws Exception if failed. */
+    @Test
+    @WithSystemProperty(key = IGNITE_OVERRIDE_WRITE_THROTTLING_ENABLED, value = "TARGET_RATIO_BASED")
+    public void testThrottleTargetRatioBased() throws Exception {
+        checkThrottling();
+    }
+
+    /** @throws Exception if failed. */
+    public void checkThrottling() throws Exception {
+        IgniteEx srv = startGrid();
+
+        srv.cluster().state(ClusterState.ACTIVE);
+
+        IgniteCache<Long, Long> cache = srv.getOrCreateCache(DEFAULT_CACHE_NAME);
+
+        long start = U.currentTimeMillis();
+
+        MetricRegistry mreg = srv.context().metric().registry(
+            metricName(DATAREGION_METRICS_PREFIX, DFLT_DATA_REG_DEFAULT_NAME));
+
+        LongAdderMetric totalThrottlingTime = mreg.findMetric("TotalThrottlingTime");
+
+        startCollectStatistics();
+
+        AtomicBoolean stop = new AtomicBoolean();
+
+        slowCheckpointEnabled.set(true);
+
+        IgniteInternalFuture<?> fut = GridTestUtils.runAsync(() -> {
+            while (!stop.get())
+                cache.put(ThreadLocalRandom.current().nextLong(1024), ThreadLocalRandom.current().nextLong());
+        });
+
+        assertTrue(waitForCondition(() -> 0 < totalThrottlingTime.value(), TIMEOUT));
+
+        stop.set(true);
+
+        AtomicInteger cnt = new AtomicInteger();
+
+        stopCollectStatisticsAndRead(new TestHandler() {
+            @Override public void pagesWriteThrottle(UUID nodeId, long endTime, long duration) {
+                assertEquals(srv.localNode().id(), nodeId);
+
+                assertTrue(start <= endTime);
+                assertTrue(duration >= 0);
+
+                cnt.incrementAndGet();
+            }
+        });
+
+        assertTrue(cnt.get() > 0);
+
+        fut.get(TIMEOUT);
+    }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
index 3041a4c..14cd9d7 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicWithPersistenceTestSuite.java
@@ -45,6 +45,7 @@ import org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteCl
 import org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotMXBeanTest;
 import org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteSnapshotManagerSelfTest;
 import org.apache.ignite.internal.processors.performancestatistics.CacheStartTest;
+import org.apache.ignite.internal.processors.performancestatistics.CheckpointTest;
 import org.apache.ignite.internal.processors.performancestatistics.ForwardReadTest;
 import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsMultipleStartTest;
 import org.apache.ignite.internal.processors.performancestatistics.PerformanceStatisticsPropertiesTest;
@@ -111,7 +112,8 @@ import org.junit.runners.Suite;
     PerformanceStatisticsPropertiesTest.class,
     PerformanceStatisticsMultipleStartTest.class,
     ForwardReadTest.class,
-    CacheStartTest.class
+    CacheStartTest.class,
+    CheckpointTest.class
 })
 public class IgniteBasicWithPersistenceTestSuite {
 }