You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2015/05/26 18:18:22 UTC

[3/4] incubator-ignite git commit: ignite-37 Improve offheap metrics for cache

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b8229df7/modules/core/src/main/java/org/apache/ignite/spi/IgniteSpiContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/IgniteSpiContext.java b/modules/core/src/main/java/org/apache/ignite/spi/IgniteSpiContext.java
index 6852b6d..55f46e5 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/IgniteSpiContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/IgniteSpiContext.java
@@ -24,7 +24,6 @@ import org.apache.ignite.internal.managers.communication.*;
 import org.apache.ignite.internal.managers.eventstorage.*;
 import org.apache.ignite.plugin.extensions.communication.*;
 import org.apache.ignite.plugin.security.*;
-import org.apache.ignite.spi.swapspace.*;
 import org.jetbrains.annotations.*;
 
 import javax.cache.*;
@@ -253,30 +252,6 @@ public interface IgniteSpiContext {
     public <K> boolean containsKey(String cacheName, K key);
 
     /**
-     * Writes object to swap.
-     *
-     * @param spaceName Swap space name.
-     * @param key Key.
-     * @param val Value.
-     * @param ldr Class loader (optional).
-     * @throws IgniteException If any exception occurs.
-     */
-    public void writeToSwap(String spaceName, Object key, @Nullable Object val, @Nullable ClassLoader ldr)
-        throws IgniteException;
-
-    /**
-     * Reads object from swap.
-     *
-     * @param spaceName Swap space name.
-     * @param key Key.
-     * @param ldr Class loader (optional).
-     * @return Swapped value.
-     * @throws IgniteException If any exception occurs.
-     */
-    @Nullable public <T> T readFromSwap(String spaceName, SwapKey key, @Nullable ClassLoader ldr)
-        throws IgniteException;
-
-    /**
      * Calculates partition number for given key.
      *
      * @param cacheName Cache name.
@@ -286,16 +261,6 @@ public interface IgniteSpiContext {
     public int partition(String cacheName, Object key);
 
     /**
-     * Removes object from swap.
-     *
-     * @param spaceName Swap space name.
-     * @param key Key.
-     * @param ldr Class loader (optional).
-     * @throws IgniteException If any exception occurs.
-     */
-    public void removeFromSwap(String spaceName, Object key, @Nullable ClassLoader ldr) throws IgniteException;
-
-    /**
      * Validates that new node can join grid topology, this method is called on coordinator
      * node before new node joins topology.
      *
@@ -322,18 +287,6 @@ public interface IgniteSpiContext {
     public SecuritySubject authenticatedSubject(UUID subjId) throws IgniteException;
 
     /**
-     * Reads swapped cache value from off-heap and swap.
-     *
-     * @param spaceName Off-heap space name.
-     * @param key Key.
-     * @param ldr Class loader for unmarshalling.
-     * @return Value.
-     * @throws IgniteException If any exception occurs.
-     */
-    @Nullable public <T> T readValueFromOffheapAndSwap(@Nullable String spaceName, Object key,
-        @Nullable ClassLoader ldr) throws IgniteException;
-
-    /**
      * Gets message formatter.
      *
      * @return Message formatter.

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b8229df7/modules/core/src/main/java/org/apache/ignite/spi/swapspace/file/FileSwapSpaceSpi.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/spi/swapspace/file/FileSwapSpaceSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/swapspace/file/FileSwapSpaceSpi.java
index e7db285..7a88426 100644
--- a/modules/core/src/main/java/org/apache/ignite/spi/swapspace/file/FileSwapSpaceSpi.java
+++ b/modules/core/src/main/java/org/apache/ignite/spi/swapspace/file/FileSwapSpaceSpi.java
@@ -387,15 +387,13 @@ public class FileSwapSpaceSpi extends IgniteSpiAdapter implements SwapSpaceSpi,
 
         Space space = space(spaceName, false);
 
-        if (space == null)
-            return;
-
-        byte[] val = space.remove(key, c != null);
+        byte[] val = space == null ? null : space.remove(key, c != null);
 
         if (c != null)
             c.apply(val);
 
-        notifyListener(EVT_SWAP_SPACE_DATA_REMOVED, spaceName);
+        if (space != null)
+             notifyListener(EVT_SWAP_SPACE_DATA_REMOVED, spaceName);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b8229df7/modules/core/src/test/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManagerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManagerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManagerSelfTest.java
index 043311e..5cfd188 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManagerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/managers/swapspace/GridSwapSpaceManagerSelfTest.java
@@ -40,7 +40,7 @@ import static org.apache.ignite.events.EventType.*;
 @GridCommonTest(group = "Kernal Self")
 public class GridSwapSpaceManagerSelfTest extends GridCommonAbstractTest {
     /** */
-    private static final String spaceName = "swapspace_mgr";
+    private static final String SPACE_NAME = "swapspace_mgr";
 
     /**
      *
@@ -64,7 +64,7 @@ public class GridSwapSpaceManagerSelfTest extends GridCommonAbstractTest {
      * @param ignite Grid instance.
      * @return Swap space manager.
      */
-    private GridSwapSpaceManager getSwapSpaceManager(Ignite ignite) {
+    private static GridSwapSpaceManager getSwapSpaceManager(Ignite ignite) {
         assert ignite != null;
 
         return ((IgniteKernal) ignite).context().swap();
@@ -89,7 +89,7 @@ public class GridSwapSpaceManagerSelfTest extends GridCommonAbstractTest {
 
                 SwapSpaceEvent e = (SwapSpaceEvent) evt;
 
-                assert spaceName.equals(e.space());
+                assert SPACE_NAME.equals(e.space());
                 assert ignite.cluster().localNode().id().equals(e.node().id());
 
                 switch (evt.type()) {
@@ -123,22 +123,28 @@ public class GridSwapSpaceManagerSelfTest extends GridCommonAbstractTest {
 
         GridSwapSpaceManager mgr = getSwapSpaceManager(ignite);
 
+        ignite.getOrCreateCache((String)null);
+
+        GridKernalContext ctx = ((IgniteKernal)ignite).context();
+
         assert mgr != null;
 
         // Empty data space.
-        assertEquals(0, mgr.swapSize(spaceName));
+        assertEquals(0, mgr.swapSize(SPACE_NAME));
+
+        String key1 = "key1";
 
-        SwapKey key = new SwapKey("key1");
+        String key2 = "key2";
 
         String val = "value";
 
-        mgr.write(spaceName, key, val.getBytes(), null);
+        mgr.write(SPACE_NAME, new SwapKey(key1), val.getBytes(), null);
 
-        mgr.write(spaceName, new SwapKey("key2"), val.getBytes(), null);
+        mgr.write(SPACE_NAME, new SwapKey(key2), val.getBytes(), null);
 
         assert storeCnt.await(10, SECONDS);
 
-        byte[] arr = mgr.read(spaceName, key, null);
+        byte[] arr = mgr.read(SPACE_NAME, new SwapKey(key1), null);
 
         assert arr != null;
 
@@ -146,7 +152,7 @@ public class GridSwapSpaceManagerSelfTest extends GridCommonAbstractTest {
 
         final GridTuple<Boolean> b = F.t(false);
 
-        mgr.remove(spaceName, key, new CI1<byte[]>() {
+        mgr.remove(SPACE_NAME, new SwapKey(key1), new CI1<byte[]>() {
             @Override public void apply(byte[] rmv) {
                 b.set(rmv != null);
             }
@@ -157,7 +163,7 @@ public class GridSwapSpaceManagerSelfTest extends GridCommonAbstractTest {
         assert rmvCnt.await(10, SECONDS);
         assert readCnt.await(10, SECONDS);
 
-        mgr.clear(spaceName);
+        mgr.clear(SPACE_NAME);
 
         assert clearCnt.await(10, SECONDS) : "Count: " + clearCnt.getCount();
     }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b8229df7/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/local/CacheLocalOffHeapAndSwapMetricsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/local/CacheLocalOffHeapAndSwapMetricsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/local/CacheLocalOffHeapAndSwapMetricsSelfTest.java
new file mode 100644
index 0000000..3d44600
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/local/CacheLocalOffHeapAndSwapMetricsSelfTest.java
@@ -0,0 +1,412 @@
+/*
+ * 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.local;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.cache.eviction.fifo.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.spi.swapspace.file.*;
+import org.apache.ignite.testframework.junits.common.*;
+
+/**
+ *
+ */
+public class CacheLocalOffHeapAndSwapMetricsSelfTest extends GridCommonAbstractTest {
+    /** Grid count. */
+    private static final int GRID_CNT = 1;
+
+    /** Keys count. */
+    private static final int KEYS_CNT = 1000;
+
+    /** Max size. */
+    private static final int MAX_SIZE = 100;
+
+    /** Entry size. */
+    private static final int ENTRY_SIZE = 86; // Calculated as allocated size divided on entries count.
+
+    /** Offheap max count. */
+    private static final int OFFHEAP_MAX_CNT = KEYS_CNT / 2;
+
+    /** Offheap max size. */
+    private static final int OFFHEAP_MAX_SIZE = ENTRY_SIZE * OFFHEAP_MAX_CNT;
+
+    /** Cache. */
+    private IgniteCache<Integer, Integer> cache;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        cfg.setSwapSpaceSpi(new FileSwapSpaceSpi());
+
+        return cfg;
+    }
+
+    /**
+     * @param offHeapSize Max off-heap size.
+     * @param swapEnabled Swap enabled.
+     */
+    private void createCache(int offHeapSize, boolean swapEnabled) {
+        CacheConfiguration ccfg = defaultCacheConfiguration();
+
+        ccfg.setStatisticsEnabled(true);
+
+        ccfg.setCacheMode(CacheMode.LOCAL);
+        ccfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
+        ccfg.setMemoryMode(CacheMemoryMode.ONHEAP_TIERED);
+
+        ccfg.setOffHeapMaxMemory(offHeapSize);
+        ccfg.setSwapEnabled(swapEnabled);
+
+        ccfg.setEvictionPolicy(new FifoEvictionPolicy(MAX_SIZE));
+
+        cache = grid(0).getOrCreateCache(ccfg);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGrids(GRID_CNT);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        super.afterTestsStopped();
+
+        stopAllGrids();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (cache != null)
+            cache.close();
+    }
+
+    /**
+     * @throws Exception if failed.
+     */
+    public void testOffHeapMetrics() throws Exception {
+        createCache(0, false);
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.put(i, i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPuts());
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapGets());
+        assertEquals(0, cache.metrics().getOffHeapHits());
+        assertEquals(0f, cache.metrics().getOffHeapHitPercentage());
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapMisses());
+        assertEquals(100f, cache.metrics().getOffHeapMissPercentage());
+        assertEquals(0, cache.metrics().getOffHeapRemovals());
+
+        assertEquals(0, cache.metrics().getOffHeapEvictions());
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapEntriesCount());
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPrimaryEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapBackupEntriesCount());
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.get(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPuts());
+        assertEquals(KEYS_CNT * 2, cache.metrics().getOffHeapGets());
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapHits());
+        assertEquals(100 * KEYS_CNT / (KEYS_CNT * 2.0), cache.metrics().getOffHeapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapMisses());
+        assertEquals(100 * KEYS_CNT / (KEYS_CNT * 2.0), cache.metrics().getOffHeapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapRemovals());
+
+        assertEquals(0, cache.metrics().getOffHeapEvictions());
+        assertEquals(KEYS_CNT - MAX_SIZE, cache.metrics().getOffHeapEntriesCount());
+        assertEquals(KEYS_CNT - MAX_SIZE, cache.metrics().getOffHeapPrimaryEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapBackupEntriesCount());
+
+        for (int i = KEYS_CNT; i < KEYS_CNT * 2; i++)
+            cache.get(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPuts());
+        assertEquals(KEYS_CNT * 3, cache.metrics().getOffHeapGets());
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapHits());
+        assertEquals(100 / 3.0, cache.metrics().getOffHeapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2, cache.metrics().getOffHeapMisses());
+        assertEquals(100 - (100 / 3.0), cache.metrics().getOffHeapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapRemovals());
+
+        assertEquals(0, cache.metrics().getOffHeapEvictions());
+        assertEquals(KEYS_CNT - MAX_SIZE, cache.metrics().getOffHeapEntriesCount());
+        assertEquals(KEYS_CNT - MAX_SIZE, cache.metrics().getOffHeapPrimaryEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapBackupEntriesCount());
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.remove(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPuts());
+        assertEquals(KEYS_CNT * 4 - MAX_SIZE, cache.metrics().getOffHeapGets());
+        assertEquals(KEYS_CNT * 2 - MAX_SIZE, cache.metrics().getOffHeapHits());
+        assertEquals(100 * (KEYS_CNT * 2.0 - MAX_SIZE) / (KEYS_CNT * 4.0 - MAX_SIZE),
+            cache.metrics().getOffHeapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2, cache.metrics().getOffHeapMisses());
+        assertEquals(100 * KEYS_CNT * 2.0 / (KEYS_CNT * 4.0 - MAX_SIZE),
+            cache.metrics().getOffHeapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2 - MAX_SIZE, cache.metrics().getOffHeapRemovals());
+
+        assertEquals(0, cache.metrics().getOffHeapEvictions());
+        assertEquals(0, cache.metrics().getOffHeapEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapPrimaryEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapBackupEntriesCount());
+    }
+
+    /**
+     * @throws Exception if failed.
+     */
+    public void testSwapMetrics() throws Exception {
+        createCache(-1, true);
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.put(i, i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getSwapPuts());
+        assertEquals(KEYS_CNT, cache.metrics().getSwapGets());
+        assertEquals(0, cache.metrics().getSwapHits());
+        assertEquals(0f, cache.metrics().getSwapHitPercentage());
+        assertEquals(KEYS_CNT, cache.metrics().getSwapMisses());
+        assertEquals(100f, cache.metrics().getSwapMissPercentage());
+        assertEquals(0, cache.metrics().getSwapRemovals());
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getSwapEntriesCount());
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.get(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getSwapPuts());
+        assertEquals(KEYS_CNT * 2, cache.metrics().getSwapGets());
+        assertEquals(KEYS_CNT, cache.metrics().getSwapHits());
+        assertEquals(100 * KEYS_CNT / (KEYS_CNT * 2.0), cache.metrics().getSwapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getSwapMisses());
+        assertEquals(100 * KEYS_CNT / (KEYS_CNT * 2.0), cache.metrics().getSwapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getSwapRemovals());
+
+        assertEquals(KEYS_CNT - MAX_SIZE, cache.metrics().getSwapEntriesCount());
+
+        for (int i = KEYS_CNT; i < KEYS_CNT * 2; i++)
+            cache.get(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getSwapPuts());
+        assertEquals(KEYS_CNT * 3, cache.metrics().getSwapGets());
+        assertEquals(KEYS_CNT, cache.metrics().getSwapHits());
+        assertEquals(100 / 3.0, cache.metrics().getSwapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2, cache.metrics().getSwapMisses());
+        assertEquals(100 - (100 / 3.0), cache.metrics().getSwapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getSwapRemovals());
+
+        assertEquals(KEYS_CNT - MAX_SIZE, cache.metrics().getSwapEntriesCount());
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.remove(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getSwapPuts());
+        assertEquals(KEYS_CNT * 4 - MAX_SIZE, cache.metrics().getSwapGets());
+        assertEquals(KEYS_CNT * 2 - MAX_SIZE, cache.metrics().getSwapHits());
+        assertEquals(100 * (KEYS_CNT * 2.0 - MAX_SIZE) / (KEYS_CNT * 4.0 - MAX_SIZE),
+            cache.metrics().getSwapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2, cache.metrics().getSwapMisses());
+        assertEquals(100 * KEYS_CNT * 2.0 / (KEYS_CNT * 4.0 - MAX_SIZE),
+            cache.metrics().getSwapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2 - MAX_SIZE, cache.metrics().getSwapRemovals());
+
+        assertEquals(0, cache.metrics().getSwapEntriesCount());
+    }
+
+    /**
+     * @throws Exception if failed.
+     */
+    public void testOffHeapAndSwapMetrics() throws Exception {
+        createCache(OFFHEAP_MAX_SIZE, true);
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.put(i, i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPuts());
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapGets());
+        assertEquals(0, cache.metrics().getOffHeapHits());
+        assertEquals(0f, cache.metrics().getOffHeapHitPercentage());
+        assertEquals(KEYS_CNT, cache.metrics().getOffHeapMisses());
+        assertEquals(100f, cache.metrics().getOffHeapMissPercentage());
+        assertEquals(0, cache.metrics().getOffHeapRemovals());
+
+        assertEquals(KEYS_CNT - MAX_SIZE - OFFHEAP_MAX_CNT, cache.metrics().getOffHeapEvictions());
+        assertEquals(OFFHEAP_MAX_CNT, cache.metrics().getOffHeapEntriesCount());
+        assertEquals(OFFHEAP_MAX_CNT, cache.metrics().getOffHeapPrimaryEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapBackupEntriesCount());
+
+        assertEquals(cache.metrics().getOffHeapEvictions(), cache.metrics().getSwapPuts());
+        assertEquals(KEYS_CNT, cache.metrics().getSwapGets());
+        assertEquals(0, cache.metrics().getSwapHits());
+        assertEquals(0f, cache.metrics().getSwapHitPercentage());
+        assertEquals(KEYS_CNT, cache.metrics().getSwapMisses());
+        assertEquals(100f, cache.metrics().getSwapMissPercentage());
+        assertEquals(0, cache.metrics().getSwapRemovals());
+
+        assertEquals(cache.metrics().getOffHeapEvictions(), cache.metrics().getSwapEntriesCount());
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.get(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPuts());
+        assertEquals(KEYS_CNT * 2, cache.metrics().getOffHeapGets());
+        assertEquals(0, cache.metrics().getOffHeapHits());
+        assertEquals(0.0, cache.metrics().getOffHeapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2, cache.metrics().getOffHeapMisses());
+        assertEquals(100.0, cache.metrics().getOffHeapMissPercentage(), 0.1);
+        assertEquals(0, cache.metrics().getOffHeapRemovals());
+
+        assertEquals(cache.metrics().getCacheEvictions() - OFFHEAP_MAX_CNT, cache.metrics().getOffHeapEvictions());
+        assertEquals(OFFHEAP_MAX_CNT, cache.metrics().getOffHeapEntriesCount());
+        assertEquals(OFFHEAP_MAX_CNT, cache.metrics().getOffHeapPrimaryEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapBackupEntriesCount());
+
+        assertEquals(cache.metrics().getOffHeapEvictions(), cache.metrics().getSwapPuts());
+        assertEquals(KEYS_CNT * 2, cache.metrics().getSwapGets());
+        assertEquals(KEYS_CNT, cache.metrics().getSwapHits());
+        assertEquals(100 * KEYS_CNT / (KEYS_CNT * 2.0), cache.metrics().getSwapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getSwapMisses());
+        assertEquals(100 * KEYS_CNT / (KEYS_CNT * 2.0), cache.metrics().getSwapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getSwapRemovals());
+
+        assertEquals(KEYS_CNT - MAX_SIZE - OFFHEAP_MAX_CNT, cache.metrics().getSwapEntriesCount());
+
+        for (int i = KEYS_CNT; i < KEYS_CNT * 2; i++)
+            cache.get(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPuts());
+        assertEquals(KEYS_CNT * 3, cache.metrics().getOffHeapGets());
+        assertEquals(0, cache.metrics().getOffHeapHits());
+        assertEquals(0.0, cache.metrics().getOffHeapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 3, cache.metrics().getOffHeapMisses());
+        assertEquals(100.0, cache.metrics().getOffHeapMissPercentage(), 0.1);
+        assertEquals(0, cache.metrics().getOffHeapRemovals());
+
+        assertEquals(cache.metrics().getCacheEvictions() - OFFHEAP_MAX_CNT, cache.metrics().getOffHeapEvictions());
+        assertEquals(OFFHEAP_MAX_CNT, cache.metrics().getOffHeapEntriesCount());
+        assertEquals(OFFHEAP_MAX_CNT, cache.metrics().getOffHeapPrimaryEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapBackupEntriesCount());
+
+        assertEquals(cache.metrics().getOffHeapEvictions(), cache.metrics().getSwapPuts());
+        assertEquals(KEYS_CNT * 3, cache.metrics().getSwapGets());
+        assertEquals(KEYS_CNT, cache.metrics().getSwapHits());
+        assertEquals(100 / 3.0, cache.metrics().getSwapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2, cache.metrics().getSwapMisses());
+        assertEquals(100 - (100 / 3.0), cache.metrics().getSwapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT, cache.metrics().getSwapRemovals());
+
+        assertEquals(KEYS_CNT - MAX_SIZE - OFFHEAP_MAX_CNT, cache.metrics().getSwapEntriesCount());
+
+        for (int i = 0; i < KEYS_CNT; i++)
+            cache.remove(i);
+
+        printStat();
+
+        assertEquals(cache.metrics().getCacheEvictions(), cache.metrics().getOffHeapPuts());
+        assertEquals(KEYS_CNT * 4 - MAX_SIZE, cache.metrics().getOffHeapGets());
+        assertEquals(OFFHEAP_MAX_CNT, cache.metrics().getOffHeapHits());
+        assertEquals(100 * OFFHEAP_MAX_CNT / (KEYS_CNT * 4.0 - MAX_SIZE),
+            cache.metrics().getOffHeapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 4 - OFFHEAP_MAX_CNT - MAX_SIZE, cache.metrics().getOffHeapMisses());
+        assertEquals(100 * (KEYS_CNT * 4 - OFFHEAP_MAX_CNT - MAX_SIZE) / (KEYS_CNT * 4.0 - MAX_SIZE),
+            cache.metrics().getOffHeapMissPercentage(), 0.1);
+        assertEquals(OFFHEAP_MAX_CNT, cache.metrics().getOffHeapRemovals());
+
+        assertEquals(cache.metrics().getCacheEvictions() - OFFHEAP_MAX_CNT, cache.metrics().getOffHeapEvictions());
+        assertEquals(0, cache.metrics().getOffHeapEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapPrimaryEntriesCount());
+        assertEquals(0, cache.metrics().getOffHeapBackupEntriesCount());
+
+        assertEquals(cache.metrics().getOffHeapEvictions(), cache.metrics().getSwapPuts());
+        assertEquals(KEYS_CNT * 4 - MAX_SIZE - OFFHEAP_MAX_CNT, cache.metrics().getSwapGets());
+        assertEquals(KEYS_CNT * 2 - MAX_SIZE - OFFHEAP_MAX_CNT, cache.metrics().getSwapHits());
+        assertEquals(100 * (KEYS_CNT * 2.0 - MAX_SIZE - OFFHEAP_MAX_CNT) / (KEYS_CNT * 4.0 - MAX_SIZE - OFFHEAP_MAX_CNT),
+            cache.metrics().getSwapHitPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2, cache.metrics().getSwapMisses());
+        assertEquals(100 * KEYS_CNT * 2.0 / (KEYS_CNT * 4.0 - MAX_SIZE - OFFHEAP_MAX_CNT),
+            cache.metrics().getSwapMissPercentage(), 0.1);
+        assertEquals(KEYS_CNT * 2 - MAX_SIZE - OFFHEAP_MAX_CNT, cache.metrics().getSwapRemovals());
+
+        assertEquals(0, cache.metrics().getSwapEntriesCount());
+    }
+
+    /**
+     * Prints stats.
+     */
+    protected void printStat() {
+        System.out.println("!!! -------------------------------------------------------");
+        System.out.println("!!! Puts: cache = " + cache.metrics().getCachePuts() +
+            ", offheap = " + cache.metrics().getOffHeapPuts() +
+            ", swap = " + cache.metrics().getSwapPuts());
+        System.out.println("!!! Gets: cache = " + cache.metrics().getCacheGets() +
+            ", offheap = " + cache.metrics().getOffHeapGets() +
+            ", swap = " + cache.metrics().getSwapGets());
+        System.out.println("!!! Removes: cache = " + cache.metrics().getCacheRemovals() +
+            ", offheap = " + cache.metrics().getOffHeapRemovals() +
+            ", swap = " + cache.metrics().getSwapRemovals());
+        System.out.println("!!! Evictions: cache = " + cache.metrics().getCacheEvictions() +
+            ", offheap = " + cache.metrics().getOffHeapEvictions() +
+            ", swap = none" );
+        System.out.println("!!! Hits: cache = " + cache.metrics().getCacheHits() +
+            ", offheap = " + cache.metrics().getOffHeapHits() +
+            ", swap = " + cache.metrics().getSwapHits());
+        System.out.println("!!! Hit(%): cache = " + cache.metrics().getCacheHitPercentage() +
+            ", offheap = " + cache.metrics().getOffHeapHitPercentage() +
+            ", swap = " + cache.metrics().getSwapHitPercentage());
+        System.out.println("!!! Misses: cache = " + cache.metrics().getCacheMisses() +
+            ", offheap = " + cache.metrics().getOffHeapMisses() +
+            ", swap = " + cache.metrics().getSwapMisses());
+        System.out.println("!!! Miss(%): cache = " + cache.metrics().getCacheMissPercentage() +
+            ", offheap = " + cache.metrics().getOffHeapMissPercentage() +
+            ", swap = " + cache.metrics().getSwapMissPercentage());
+        System.out.println("!!! Entries: cache = " + cache.metrics().getSize() +
+            ", offheap = " + cache.metrics().getOffHeapEntriesCount() +
+            ", swap = " + cache.metrics().getSwapEntriesCount());
+        System.out.println("!!! Size: cache = none" +
+            ", offheap = " + cache.metrics().getOffHeapAllocatedSize() +
+            ", swap = " + cache.metrics().getSwapSize());
+        System.out.println();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b8229df7/modules/core/src/test/java/org/apache/ignite/testframework/GridSpiTestContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/GridSpiTestContext.java b/modules/core/src/test/java/org/apache/ignite/testframework/GridSpiTestContext.java
index bc04f90..5867fb8 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/GridSpiTestContext.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/GridSpiTestContext.java
@@ -29,7 +29,7 @@ import org.apache.ignite.lang.*;
 import org.apache.ignite.plugin.extensions.communication.*;
 import org.apache.ignite.plugin.security.*;
 import org.apache.ignite.spi.*;
-import org.apache.ignite.spi.swapspace.*;
+
 import org.jetbrains.annotations.*;
 
 import java.io.*;
@@ -447,28 +447,11 @@ public class GridSpiTestContext implements IgniteSpiContext {
     }
 
     /** {@inheritDoc} */
-    @Override public void writeToSwap(String spaceName, Object key, @Nullable Object val,
-        @Nullable ClassLoader ldr) {
-        /* No-op. */
-    }
-
-    /** {@inheritDoc} */
-    @Override public <T> T readFromSwap(String spaceName, SwapKey key, @Nullable ClassLoader ldr) {
-        return null;
-    }
-
-    /** {@inheritDoc} */
     @Override public int partition(String cacheName, Object key) {
         return -1;
     }
 
     /** {@inheritDoc} */
-    @Override public void removeFromSwap(String spaceName, Object key,
-        @Nullable ClassLoader ldr) {
-        // No-op.
-    }
-
-    /** {@inheritDoc} */
     @Nullable @Override public IgniteNodeValidationResult validateNode(ClusterNode node) {
         return null;
     }
@@ -484,12 +467,6 @@ public class GridSpiTestContext implements IgniteSpiContext {
     }
 
     /** {@inheritDoc} */
-    @Nullable @Override public <T> T readValueFromOffheapAndSwap(@Nullable String spaceName, Object key,
-        @Nullable ClassLoader ldr) {
-        return null;
-    }
-
-    /** {@inheritDoc} */
     @Override public MessageFormatter messageFormatter() {
         if (formatter == null) {
             formatter = new MessageFormatter() {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b8229df7/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
index 1adf55f..9a0e5fc 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheMetricsSelfTestSuite.java
@@ -39,6 +39,7 @@ public class IgniteCacheMetricsSelfTestSuite extends TestSuite {
         suite.addTestSuite(GridCacheReplicatedMetricsSelfTest.class);
         suite.addTestSuite(GridCachePartitionedMetricsSelfTest.class);
         suite.addTestSuite(GridCachePartitionedHitsAndMissesSelfTest.class);
+        suite.addTestSuite(CacheLocalOffHeapAndSwapMetricsSelfTest.class);
 
         // Atomic cache.
         suite.addTestSuite(GridCacheAtomicLocalMetricsSelfTest.class);