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 2017/04/28 12:40:14 UTC

[5/9] ignite git commit: IGNITE-5072 - Updated memory metrics to comply with other metrics

IGNITE-5072 - Updated memory metrics to comply with other metrics


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/11c23b62
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/11c23b62
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/11c23b62

Branch: refs/heads/ignite-5075-cacheStart
Commit: 11c23b628af0cec6cf8ddf2da9a510c460877f22
Parents: f5fe301
Author: Sergey Chugunov <se...@gmail.com>
Authored: Thu Apr 27 19:56:02 2017 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Thu Apr 27 19:56:02 2017 +0300

----------------------------------------------------------------------
 examples/config/example-memory-policies.xml     |  16 +-
 .../benchmarks/jmh/tree/BPlusTreeBenchmark.java |  15 +-
 .../src/main/java/org/apache/ignite/Ignite.java |   1 -
 .../java/org/apache/ignite/MemoryMetrics.java   |  73 ++--
 .../org/apache/ignite/cache/CacheMetrics.java   |   8 -
 .../configuration/DataPageEvictionMode.java     |   4 +-
 .../configuration/MemoryConfiguration.java      | 109 ++++-
 .../MemoryPolicyConfiguration.java              |  82 +++-
 .../apache/ignite/internal/IgniteKernal.java    |  11 +-
 .../ignite/internal/mem/DirectMemory.java       |  55 ---
 .../internal/mem/DirectMemoryProvider.java      |  19 +-
 .../mem/file/MappedFileMemoryProvider.java      | 153 ++-----
 .../mem/unsafe/UnsafeMemoryProvider.java        |  69 ++--
 .../pagemem/impl/PageMemoryNoStoreImpl.java     | 408 +++++++++++++------
 .../cache/CacheClusterMetricsMXBeanImpl.java    |   5 -
 .../cache/CacheLocalMetricsMXBeanImpl.java      |   5 -
 .../processors/cache/CacheMetricsImpl.java      |   5 -
 .../processors/cache/CacheMetricsSnapshot.java  |  13 -
 .../IgniteCacheDatabaseSharedManager.java       | 235 +++++++----
 .../cache/database/MemoryMetricsImpl.java       |  24 +-
 .../cache/database/MemoryMetricsMXBeanImpl.java | 108 +++++
 .../cache/database/MemoryMetricsSnapshot.java   |  85 ++++
 .../processors/cache/database/MemoryPolicy.java |   7 +-
 .../evict/FairFifoPageEvictionTracker.java      |   6 +-
 .../evict/PageAbstractEvictionTracker.java      |  85 +---
 .../evict/Random2LruPageEvictionTracker.java    |   6 +-
 .../evict/RandomLruPageEvictionTracker.java     |   6 +-
 .../processors/igfs/IgfsDataManager.java        |   2 +-
 .../platform/cache/PlatformCache.java           |   1 -
 .../utils/PlatformConfigurationUtils.java       |  18 +-
 .../service/GridServiceProcessor.java           |   9 +-
 .../ignite/internal/util/IgniteUtils.java       |  28 +-
 .../visor/node/VisorMemoryConfiguration.java    |   2 +-
 .../node/VisorMemoryPolicyConfiguration.java    |   2 +-
 .../ignite/mxbean/CacheMetricsMXBean.java       |   4 -
 .../ignite/mxbean/MemoryMetricsMXBean.java      |  83 ++--
 .../internal/ClusterNodeMetricsSelfTest.java    |   6 +-
 .../pagemem/impl/PageMemoryNoLoadSelfTest.java  |  18 +-
 .../cache/CacheConfigurationLeakTest.java       |   2 +-
 .../CacheMemoryPolicyConfigurationTest.java     |  10 +-
 .../cache/MemoryPolicyConfigValidationTest.java | 121 +++++-
 .../MemoryPolicyInitializationTest.java         |  16 +-
 .../paged/PageEvictionAbstractTest.java         |   4 +-
 .../TxPessimisticDeadlockDetectionTest.java     |   2 +-
 .../processors/database/BPlusTreeSelfTest.java  |  26 +-
 .../database/FreeListImplSelfTest.java          |  26 +-
 .../database/IgniteDbDynamicCacheSelfTest.java  |   2 +-
 .../database/MemoryMetricsSelfTest.java         |   5 +-
 .../database/MetadataStorageSelfTest.java       |  21 +-
 .../processors/igfs/IgfsSizeSelfTest.java       |   2 +-
 .../platform/PlatformCacheWriteMetricsTask.java |   5 -
 ...stributedPartitionQueryAbstractSelfTest.java |   5 +-
 .../IgniteCacheQueryNodeRestartSelfTest2.java   |   7 +-
 .../index/DynamicIndexAbstractSelfTest.java     |   6 +-
 .../h2/database/InlineIndexHelperTest.java      |  40 +-
 .../cpp/core-test/config/cache-identity-32.xml  |   7 +-
 .../cpp/core-test/config/cache-query-32.xml     |   6 +-
 .../config/cache-query-continuous-32.xml        |   6 +-
 .../cpp/core-test/config/cache-store-32.xml     |   6 +-
 .../cpp/core-test/config/cache-test-32.xml      |   6 +-
 .../cpp/odbc-test/config/queries-test-32.xml    |   6 +-
 .../odbc-test/config/queries-test-noodbc-32.xml |   6 +-
 .../Cache/CacheConfigurationTest.cs             |   3 +-
 .../Cache/CacheMetricsTest.cs                   |   1 -
 .../Config/spring-test.xml                      |  14 +
 .../IgniteConfigurationSerializerTest.cs        |  17 +-
 .../IgniteConfigurationTest.cs                  |  32 +-
 .../Cache/Configuration/DataPageEvictionMode.cs |   4 +-
 .../Cache/Configuration/MemoryConfiguration.cs  |  28 +-
 .../Configuration/MemoryPolicyConfiguration.cs  |  34 +-
 .../Apache.Ignite.Core/Cache/ICacheMetrics.cs   |   8 -
 .../IgniteConfigurationSection.xsd              |  16 +-
 .../Impl/Cache/CacheMetricsImpl.cs              |   7 -
 .../Apache.Ignite.Core/Impl/NativeMethods.cs    |  44 ++
 pom.xml                                         |  32 +-
 75 files changed, 1484 insertions(+), 885 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/examples/config/example-memory-policies.xml
----------------------------------------------------------------------
diff --git a/examples/config/example-memory-policies.xml b/examples/config/example-memory-policies.xml
index 121b8a5..86c7502 100644
--- a/examples/config/example-memory-policies.xml
+++ b/examples/config/example-memory-policies.xml
@@ -38,6 +38,8 @@
                 <property name="defaultMemoryPolicyName" value="Default_Region"/>
                 <!-- Setting the page size to 4 KB -->
                 <property name="pageSize" value="4096"/>
+                <property name="systemCacheInitialSize" value="#{40 * 1024 * 1024}"/>
+                <property name="systemCacheMaxSize" value="#{40 * 1024 * 1024}"/>
 
                 <!-- Defining several memory policies for different memory regions -->
                 <property name="memoryPolicies">
@@ -49,7 +51,7 @@
                         <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
                             <property name="name" value="Default_Region"/>
                             <!-- 100 MB memory region with disabled eviction -->
-                            <property name="size" value="#{100 * 1024 * 1024}"/>
+                            <property name="initialSize" value="#{100 * 1024 * 1024}"/>
                         </bean>
 
                         <!--
@@ -57,8 +59,10 @@
                         -->
                         <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
                             <property name="name" value="20MB_Region_Eviction"/>
-                            <!-- 20 MB memory region. -->
-                            <property name="size" value="#{20 * 1024 * 1024}"/>
+                            <!-- Memory region of 20 MB initial size. -->
+                            <property name="initialSize" value="#{20 * 1024 * 1024}"/>
+                            <!-- Maximum size is 40 MB. -->
+                            <property name="maxSize" value="#{40 * 1024 * 1024}"/>
                             <!-- Enabling eviction for this memory region -->
                             <property name="pageEvictionMode" value="RANDOM_2_LRU"/>
                         </bean>
@@ -69,8 +73,10 @@
                         -->
                         <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
                             <property name="name" value="15MB_Region_Swapping"/>
-                            <!-- 15 MB memory region. -->
-                            <property name="size" value="#{15 * 1024 * 1024}"/>
+                            <!-- Memory region of 15 MB initial size. -->
+                            <property name="initialSize" value="#{15 * 1024 * 1024}"/>
+                            <!-- Maximum size is 30 MB. -->
+                            <property name="maxSize" value="#{30 * 1024 * 1024}"/>
                             <!-- Setting a name of the swapping file. -->
                             <property name="swapFilePath" value="memoryPolicyExampleSwap"/>
                         </bean>

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
index 5833e1f..c9ad0cf 100644
--- a/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
+++ b/modules/benchmarks/src/main/java/org/apache/ignite/internal/benchmarks/jmh/tree/BPlusTreeBenchmark.java
@@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentLinkedDeque;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicLong;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
 import org.apache.ignite.internal.benchmarks.jmh.JmhAbstractBenchmark;
 import org.apache.ignite.internal.benchmarks.jmh.runner.JmhIdeBenchmarkRunner;
 import org.apache.ignite.internal.mem.unsafe.UnsafeMemoryProvider;
@@ -209,12 +210,14 @@ public class BPlusTreeBenchmark extends JmhAbstractBenchmark {
         for (int i = 0; i < sizes.length; i++)
             sizes[i] = 1024 * MB / CPUS;
 
+        MemoryPolicyConfiguration plcCfg = new MemoryPolicyConfiguration().setMaxSize(1024 * MB);
+
         PageMemory pageMem = new PageMemoryNoStoreImpl(new JavaLogger(),
-            new UnsafeMemoryProvider(sizes),
+            new UnsafeMemoryProvider(new JavaLogger()),
             null,
             PAGE_SIZE,
-            null,
-            new MemoryMetricsImpl(null),
+            plcCfg,
+            new MemoryMetricsImpl(plcCfg),
             false);
 
         pageMem.start();
@@ -281,8 +284,7 @@ public class BPlusTreeBenchmark extends JmhAbstractBenchmark {
         }
 
         /** {@inheritDoc} */
-        @Override public Long getLookupRow(BPlusTree<Long,?> tree, long pageAddr, int idx)
-            throws IgniteCheckedException {
+        @Override public Long getLookupRow(BPlusTree<Long,?> tree, long pageAddr, int idx) {
             return PageUtils.getLong(pageAddr, offset(idx));
         }
     }
@@ -318,8 +320,7 @@ public class BPlusTreeBenchmark extends JmhAbstractBenchmark {
         }
 
         /** {@inheritDoc} */
-        @Override public Long getLookupRow(BPlusTree<Long,?> tree, long pageAddr, int idx)
-            throws IgniteCheckedException {
+        @Override public Long getLookupRow(BPlusTree<Long,?> tree, long pageAddr, int idx) {
             return PageUtils.getLong(pageAddr, offset(idx));
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/Ignite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/Ignite.java b/modules/core/src/main/java/org/apache/ignite/Ignite.java
index 7445264..267f4f2 100644
--- a/modules/core/src/main/java/org/apache/ignite/Ignite.java
+++ b/modules/core/src/main/java/org/apache/ignite/Ignite.java
@@ -615,7 +615,6 @@ public interface Ignite extends AutoCloseable {
      */
     public void resetLostPartitions(Collection<String> cacheNames);
 
-
     /**
      * Returns collection {@link MemoryMetrics} objects providing information about memory usage in current Ignite instance.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/MemoryMetrics.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/MemoryMetrics.java b/modules/core/src/main/java/org/apache/ignite/MemoryMetrics.java
index b4097d1..96eedfe 100644
--- a/modules/core/src/main/java/org/apache/ignite/MemoryMetrics.java
+++ b/modules/core/src/main/java/org/apache/ignite/MemoryMetrics.java
@@ -17,36 +17,45 @@
 
 package org.apache.ignite;
 
+import org.apache.ignite.configuration.MemoryConfiguration;
+import org.apache.ignite.configuration.MemoryPolicyConfiguration;
+import org.apache.ignite.mxbean.MemoryMetricsMXBean;
+
 /**
- * Interface provides methods to access metrics of memory usage on local instance of Ignite.
+ * An interface to collect metrics about page memory usage on Ignite node. Overall page memory architecture
+ * is described in {@link MemoryConfiguration} javadoc.
+ * <p>
+ * As multiple page memories may be configured on a single Ignite node; memory metrics will be collected
+ * for each page memory separately.
+ * </p>
+ * <p>
+ * There are two ways to access metrics on local node.
+ * <ol>
+ *     <li>
+ *       Firstly, collection of metrics can be obtained through {@link Ignite#memoryMetrics()} call.<br/>
+ *       Please pay attention that this call returns snapshots of memory metrics and not live objects.
+ *     </li>
+ *     <li>
+ *       Secondly, all {@link MemoryMetrics} on local node are exposed through JMX interface. <br/>
+ *       See {@link MemoryMetricsMXBean} interface describing information provided about metrics
+ *       and page memory configuration.
+ *     </li>
+ * </ol>
+ * </p>
+ * <p>
+ * Also users must be aware that using memory metrics has some overhead and for performance reasons is turned off
+ * by default.
+ * For turning them on both {@link MemoryPolicyConfiguration#setMetricsEnabled(boolean)} configuration property
+ * or {@link MemoryMetricsMXBean#enableMetrics()} method of JMX bean can be used.
+ * </p>
  */
 public interface MemoryMetrics {
     /**
-     * @return Memory policy name.
+     * @return Name of memory region metrics are collected for.
      */
     public String getName();
 
     /**
-     * @return Returns size (in MBytes) of MemoryPolicy observed by this MemoryMetrics MBean.
-     */
-    public int getSize();
-
-    /**
-     * @return Path of memory-mapped file used to swap PageMemory pages to disk.
-     */
-    public String getSwapFilePath();
-
-    /**
-     * Enables collecting memory metrics.
-     */
-    public void enableMetrics();
-
-    /**
-     * Disables collecting memory metrics.
-     */
-    public void disableMetrics();
-
-    /**
      * @return Total number of allocated pages.
      */
     public long getTotalAllocatedPages();
@@ -72,24 +81,4 @@ public interface MemoryMetrics {
      * @return Free space to overall size ratio across all pages in FreeList.
      */
     public float getPagesFillFactor();
-
-    /**
-     * Sets interval of time (in seconds) to monitor allocation rate.
-     *
-     * E.g. after setting rateTimeInterval to 60 seconds subsequent calls to {@link #getAllocationRate()}
-     * will return average allocation rate (pages per second) for the last minute.
-     *
-     * @param rateTimeInterval Time interval used to calculate allocation/eviction rate.
-     */
-    public void rateTimeInterval(int rateTimeInterval);
-
-    /**
-     * Sets number of subintervals the whole rateTimeInterval will be split into to calculate allocation rate,
-     * 5 by default.
-     * Setting it to bigger number allows more precise calculation and smaller drops of allocationRate metric
-     * when next subinterval has to be recycled but introduces bigger calculation overhead.
-     *
-     * @param subInts Number of subintervals.
-     */
-    public void subIntervals(int subInts);
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/cache/CacheMetrics.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/CacheMetrics.java b/modules/core/src/main/java/org/apache/ignite/cache/CacheMetrics.java
index c0eb98e..3e25aa5 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/CacheMetrics.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/CacheMetrics.java
@@ -109,7 +109,6 @@ public interface CacheMetrics {
      */
     public float getAverageRemoveTime();
 
-
     /**
      * The mean time to execute tx commit.
      *
@@ -230,13 +229,6 @@ public interface CacheMetrics {
     public long getOffHeapAllocatedSize();
 
     /**
-     * Gets off-heap memory maximum size.
-     *
-     * @return Off-heap memory maximum size.
-     */
-    public long getOffHeapMaxSize();
-
-    /**
      * Gets number of non-{@code null} values in the cache.
      *
      * @return Number of non-{@code null} values in the cache.

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java b/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java
index 1aec15a..f61e870 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/DataPageEvictionMode.java
@@ -33,9 +33,9 @@ public enum DataPageEvictionMode {
      * <ul>
      * <li>Once a memory region defined by a memory policy is configured, an off-heap array is allocated to track
      * last usage timestamp for every individual data page. The size of the array is calculated this way - size =
-     * ({@link MemoryPolicyConfiguration#getSize()} / {@link MemoryConfiguration#pageSize})</li>
+     * ({@link MemoryPolicyConfiguration#getMaxSize()} / {@link MemoryConfiguration#pageSize})</li>
      * <li>When a data page is accessed, its timestamp gets updated in the tracking array. The page index in the
-     * tracking array is calculated this way - index = (pageAddress / {@link MemoryPolicyConfiguration#getSize()}</li>
+     * tracking array is calculated this way - index = (pageAddress / {@link MemoryPolicyConfiguration#getMaxSize()}</li>
      * <li>When it's required to evict some pages, the algorithm randomly chooses 5 indexes from the tracking array and
      * evicts a page with the latest timestamp. If some of the indexes point to non-data pages (index or system pages)
      * then the algorithm picks other pages.</li>

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/configuration/MemoryConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/MemoryConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/MemoryConfiguration.java
index f88a95a..cadc033 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/MemoryConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/MemoryConfiguration.java
@@ -33,7 +33,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
  * <p>
  * If initial size of the default memory region doesn't satisfy requirements or it's required to have multiple memory
  * regions with different properties then {@link MemoryPolicyConfiguration} can be used for both scenarios.
- * For instance, Using memory policies you can define memory regions of different maximum size, eviction policies,
+ * For instance, using memory policies you can define memory regions of different maximum size, eviction policies,
  * swapping options, etc. Once you define a new memory region you can bind particular Ignite caches to it.
  * <p>
  * To learn more about memory policies refer to {@link MemoryPolicyConfiguration} documentation.
@@ -42,14 +42,14 @@ import org.apache.ignite.internal.util.typedef.internal.U;
  *     {@code
  *     <property name="memoryConfiguration">
  *         <bean class="org.apache.ignite.configuration.MemoryConfiguration">
- *             <property name="systemCacheMemorySize" value="#{100 * 1024 * 1024}"/>
+ *             <property name="systemCacheInitialSize" value="#{100 * 1024 * 1024}"/>
  *             <property name="defaultMemoryPolicyName" value="default_mem_plc"/>
  *
  *             <property name="memoryPolicies">
  *                 <list>
  *                     <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
  *                         <property name="name" value="default_mem_plc"/>
- *                         <property name="size" value="#{5 * 1024 * 1024 * 1024}"/>
+ *                         <property name="initialSize" value="#{5 * 1024 * 1024 * 1024}"/>
  *                     </bean>
  *                 </list>
  *             </property>
@@ -62,11 +62,22 @@ public class MemoryConfiguration implements Serializable {
     /** */
     private static final long serialVersionUID = 0L;
 
-    /** Default memory policy's size (1 GB). */
-    public static final long DFLT_MEMORY_POLICY_SIZE = 1024 * 1024 * 1024;
+    /** Default memory policy start size (256 MB). */
+    public static final long DFLT_MEMORY_POLICY_INITIAL_SIZE = 256 * 1024 * 1024;
 
-    /** Default size of a memory chunk for the system cache (100 MB). */
-    public static final long DFLT_SYS_CACHE_MEM_SIZE = 100 * 1024 * 1024;
+    /** Fraction of available memory to allocate for default MemoryPolicy. */
+    private static final double DFLT_MEMORY_POLICY_FRACTION = 0.8;
+
+    /** Default memory policy's size is 80% of physical memory available on current machine. */
+    public static final long DFLT_MEMORY_POLICY_MAX_SIZE = Math.max(
+        (long)(DFLT_MEMORY_POLICY_FRACTION * U.getTotalMemoryAvailable()),
+        DFLT_MEMORY_POLICY_INITIAL_SIZE);
+
+    /** Default initial size of a memory chunk for the system cache (40 MB). */
+    private static final long DFLT_SYS_CACHE_INIT_SIZE = 40 * 1024 * 1024;
+
+    /** Default max size of a memory chunk for the system cache (100 MB). */
+    private static final long DFLT_SYS_CACHE_MAX_SIZE = 100 * 1024 * 1024;
 
     /** Default memory page size. */
     public static final int DFLT_PAGE_SIZE = 2 * 1024;
@@ -74,8 +85,11 @@ public class MemoryConfiguration implements Serializable {
     /** This name is assigned to default MemoryPolicy if no user-defined default MemPlc is specified */
     public static final String DFLT_MEM_PLC_DEFAULT_NAME = "default";
 
-    /** Size of a memory chunk reserved for system cache needs. */
-    private long sysCacheMemSize = DFLT_SYS_CACHE_MEM_SIZE;
+    /** Size of a memory chunk reserved for system cache initially. */
+    private long sysCacheInitSize = DFLT_SYS_CACHE_INIT_SIZE;
+
+    /** Maximum size of system cache. */
+    private long sysCacheMaxSize = DFLT_SYS_CACHE_MAX_SIZE;
 
     /** Memory page size. */
     private int pageSize = DFLT_PAGE_SIZE;
@@ -86,27 +100,55 @@ public class MemoryConfiguration implements Serializable {
     /** A name of the memory policy that defines the default memory region. */
     private String dfltMemPlcName = DFLT_MEM_PLC_DEFAULT_NAME;
 
+    /** Size of memory (in bytes) to use for default MemoryPolicy. */
+    private Long dfltMemPlcSize;
+
     /** Memory policies. */
     private MemoryPolicyConfiguration[] memPlcs;
 
     /**
-     * Gets size of a memory chunk reserved for system cache needs.
+     * Initial size of a memory region reserved for system cache.
+     *
+     * @return Size in bytes.
+     */
+    public long getSystemCacheInitialSize() {
+        return sysCacheInitSize;
+    }
+
+    /**
+     * Sets initial size of a memory region reserved for system cache.
+     *
+     * Default value is {@link #DFLT_SYS_CACHE_INIT_SIZE}
+     *
+     * @param sysCacheInitSize Size in bytes.
+     *
+     * @return {@code this} for chaining.
+     */
+    public MemoryConfiguration setSystemCacheInitialSize(long sysCacheInitSize) {
+        this.sysCacheInitSize = sysCacheInitSize;
+
+        return this;
+    }
+
+    /**
+     * Maximum memory region size reserved for system cache.
      *
      * @return Size in bytes.
      */
-    public long getSystemCacheMemorySize() {
-        return sysCacheMemSize;
+    public long getSystemCacheMaxSize() {
+        return sysCacheMaxSize;
     }
 
     /**
-     * Sets the size of a memory chunk reserved for system cache needs.
+     * Sets maximum memory region size reserved for system cache. The total size should not be less than 10 MB
+     * due to internal data structures overhead.
      *
-     * Default value is {@link #DFLT_SYS_CACHE_MEM_SIZE}
+     * @param sysCacheMaxSize Maximum size in bytes for system cache memory region.
      *
-     * @param sysCacheMemSize Size in bytes.
+     * @return {@code this} for chaining.
      */
-    public MemoryConfiguration setSystemCacheMemorySize(long sysCacheMemSize) {
-        this.sysCacheMemSize = sysCacheMemSize;
+    public MemoryConfiguration setSystemCacheMaxSize(long sysCacheMaxSize) {
+        this.sysCacheMaxSize = sysCacheMaxSize;
 
         return this;
     }
@@ -171,7 +213,12 @@ public class MemoryConfiguration implements Serializable {
     public MemoryPolicyConfiguration createDefaultPolicyConfig() {
         MemoryPolicyConfiguration memPlc = new MemoryPolicyConfiguration();
 
-        memPlc.setSize(DFLT_MEMORY_POLICY_SIZE);
+        long maxSize = (dfltMemPlcSize != null) ? dfltMemPlcSize : DFLT_MEMORY_POLICY_MAX_SIZE;
+
+        if (maxSize < DFLT_MEMORY_POLICY_INITIAL_SIZE)
+            memPlc.setInitialSize(maxSize);
+
+        memPlc.setMaxSize(maxSize);
 
         return memPlc;
     }
@@ -198,6 +245,32 @@ public class MemoryConfiguration implements Serializable {
     }
 
     /**
+     * Gets a size for default memory policy overridden by user.
+     *
+     * @return default memory policy size overridden by user or -1 if nothing was specified.
+     */
+    public long getDefaultMemoryPolicySize() {
+        return (dfltMemPlcSize != null) ? dfltMemPlcSize : -1;
+    }
+
+    /**
+     * Overrides size of default memory policy which is created automatically.
+     *
+     * If user doesn't specify any memory policy configuration, a default one with default size
+     * (80% of available RAM) is created by Ignite.
+     *
+     * This property allows user to specify desired size of default memory policy
+     * without having to use more verbose syntax of MemoryPolicyConfiguration elements.
+     *
+     * @param dfltMemPlcSize Size of default memory policy overridden by user.
+     */
+    public MemoryConfiguration setDefaultMemoryPolicySize(long dfltMemPlcSize) {
+        this.dfltMemPlcSize = dfltMemPlcSize;
+
+        return this;
+    }
+
+    /**
      * Gets a name of default memory policy.
      *
      * @return A name of a custom memory policy configured with {@code MemoryConfiguration} or {@code null} of the

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java
index d0adcf9..55da5bd 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/MemoryPolicyConfiguration.java
@@ -39,18 +39,19 @@ import static org.apache.ignite.configuration.MemoryConfiguration.DFLT_MEM_PLC_D
  *                 <list>
  *                      <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
  *                          <property name="name" value="Default_Region"/>
- *                          <property name="size" value="#{100 * 1024 * 1024}"/>
+ *                          <property name="initialSize" value="#{100 * 1024 * 1024}"/>
  *                      </bean>
  *
  *                      <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
  *                          <property name="name" value="20MB_Region_Eviction"/>
- *                          <property name="size" value="#{20 * 1024 * 1024}"/>
+ *                          <property name="initialSize" value="#{20 * 1024 * 1024}"/>
  *                          <property name="pageEvictionMode" value="RANDOM_2_LRU"/>
  *                      </bean>
  *
  *                      <bean class="org.apache.ignite.configuration.MemoryPolicyConfiguration">
  *                          <property name="name" value="25MB_Region_Swapping"/>
- *                          <property name="size" value="#{25 * 1024 * 1024}"/>
+ *                          <property name="initialSize" value="#{25 * 1024 * 1024}"/>
+ *                          <property name="initialSize" value="#{100 * 1024 * 1024}"/>
  *                          <property name="swapFilePath" value="memoryPolicyExampleSwap"/>
  *                      </bean>
  *                  </list>
@@ -62,11 +63,17 @@ public final class MemoryPolicyConfiguration implements Serializable {
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** Default metrics enabled flag. */
+    public static final boolean DFLT_METRICS_ENABLED = false;
+
     /** Memory policy name. */
     private String name = DFLT_MEM_PLC_DEFAULT_NAME;
 
+    /** Memory policy start size. */
+    private long initialSize = MemoryConfiguration.DFLT_MEMORY_POLICY_INITIAL_SIZE;
+
     /** Memory policy maximum size. */
-    private long size;
+    private long maxSize = MemoryConfiguration.DFLT_MEMORY_POLICY_MAX_SIZE;
 
     /** An optional path to a memory mapped file for this memory policy. */
     private String swapFilePath;
@@ -83,6 +90,9 @@ public final class MemoryPolicyConfiguration implements Serializable {
     /** Minimum number of empty pages in reuse lists. */
     private int emptyPagesPoolSize = 100;
 
+    /** */
+    private boolean metricsEnabled = DFLT_METRICS_ENABLED;
+
     /**
      * Gets memory policy name.
      *
@@ -98,6 +108,7 @@ public final class MemoryPolicyConfiguration implements Serializable {
      * If not specified, {@link MemoryConfiguration#DFLT_MEM_PLC_DEFAULT_NAME} value is used.
      *
      * @param name Memory policy name.
+     * @return {@code this} for chaining.
      */
     public MemoryPolicyConfiguration setName(String name) {
         this.name = name;
@@ -111,16 +122,42 @@ public final class MemoryPolicyConfiguration implements Serializable {
      *
      * @return Size in bytes.
      */
-    public long getSize() {
-        return size;
+    public long getMaxSize() {
+        return maxSize;
     }
 
     /**
      * Sets maximum memory region size defined by this memory policy. The total size should not be less than 10 MB
      * due to the internal data structures overhead.
+     *
+     * @param maxSize Maximum memory policy size in bytes.
+     * @return {@code this} for chaining.
      */
-    public MemoryPolicyConfiguration setSize(long size) {
-        this.size = size;
+    public MemoryPolicyConfiguration setMaxSize(long maxSize) {
+        this.maxSize = maxSize;
+
+        return this;
+    }
+
+    /**
+     * Gets initial memory region size defined by this memory policy. When the used memory size exceeds this value,
+     * new chunks of memory will be allocated.
+     *
+     * @return Memory policy start size.
+     */
+    public long getInitialSize() {
+        return initialSize;
+    }
+
+    /**
+     * Sets initial memory region size defined by this memory policy. When the used memory size exceeds this value,
+     * new chunks of memory will be allocated.
+     *
+     * @param initialSize Memory policy initial size.
+     * @return {@code this} for chaining.
+     */
+    public MemoryPolicyConfiguration setInitialSize(long initialSize) {
+        this.initialSize = initialSize;
 
         return this;
     }
@@ -140,6 +177,7 @@ public final class MemoryPolicyConfiguration implements Serializable {
      * Sets a path to the memory-mapped file.
      *
      * @param swapFilePath A Path to the memory mapped file.
+     * @return {@code this} for chaining.
      */
     public MemoryPolicyConfiguration setSwapFilePath(String swapFilePath) {
         this.swapFilePath = swapFilePath;
@@ -150,7 +188,7 @@ public final class MemoryPolicyConfiguration implements Serializable {
     /**
      * Gets memory pages eviction mode. If {@link DataPageEvictionMode#DISABLED} is used (default) then an out of
      * memory exception will be thrown if the memory region usage, defined by this memory policy, goes beyond its
-     * capacity which is {@link #getSize()}.
+     * capacity which is {@link #getMaxSize()}.
      *
      * @return Memory pages eviction algorithm. {@link DataPageEvictionMode#DISABLED} used by default.
      */
@@ -162,6 +200,7 @@ public final class MemoryPolicyConfiguration implements Serializable {
      * Sets memory pages eviction mode.
      *
      * @param evictionMode Eviction mode.
+     * @return {@code this} for chaining.
      */
     public MemoryPolicyConfiguration setPageEvictionMode(DataPageEvictionMode evictionMode) {
         pageEvictionMode = evictionMode;
@@ -183,6 +222,7 @@ public final class MemoryPolicyConfiguration implements Serializable {
      * Sets memory pages eviction threshold.
      *
      * @param evictionThreshold Eviction threshold.
+     * @return {@code this} for chaining.
      */
     public MemoryPolicyConfiguration setEvictionThreshold(double evictionThreshold) {
         this.evictionThreshold = evictionThreshold;
@@ -213,10 +253,34 @@ public final class MemoryPolicyConfiguration implements Serializable {
      * Increase this parameter if {@link IgniteOutOfMemoryException} occurred with enabled page eviction.
      *
      * @param emptyPagesPoolSize Empty pages pool size.
+     * @return {@code this} for chaining.
      */
     public MemoryPolicyConfiguration setEmptyPagesPoolSize(int emptyPagesPoolSize) {
         this.emptyPagesPoolSize = emptyPagesPoolSize;
 
         return this;
     }
+
+    /**
+     * Gets whether memory metrics are enabled by default on node startup. Memory metrics can be enabled and disabled
+     * at runtime via memory metrics MX bean.
+     *
+     * @return Metrics enabled flag.
+     */
+    public boolean isMetricsEnabled() {
+        return metricsEnabled;
+    }
+
+    /**
+     * Sets memory metrics enabled flag. If this flag is {@code true}, metrics will be enabled on node startup.
+     * Memory metrics can be enabled and disabled at runtime via memory metrics MX bean.
+     *
+     * @param metricsEnabled Metrics enanabled flag.
+     * @return {@code this} for chaining.
+     */
+    public MemoryPolicyConfiguration setMetricsEnabled(boolean metricsEnabled) {
+        this.metricsEnabled = metricsEnabled;
+
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
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 f0bf29b..8ba6a88 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
@@ -2434,7 +2434,7 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
             return;
 
         U.log(log, "System cache's MemoryPolicy size is configured to " +
-            (memCfg.getSystemCacheMemorySize() / (1024 * 1024)) + " MB. " +
+            (memCfg.getSystemCacheInitialSize() / (1024 * 1024)) + " MB. " +
             "Use MemoryConfiguration.systemCacheMemorySize property to change the setting.");
     }
 
@@ -3399,7 +3399,14 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
 
     /** {@inheritDoc} */
     @Override public Collection<MemoryMetrics> memoryMetrics() {
-        return ctx.cache().context().database().memoryMetrics();
+        guard();
+
+        try {
+            return ctx.cache().context().database().memoryMetrics();
+        }
+        finally {
+            unguard();
+        }
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemory.java b/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemory.java
deleted file mode 100644
index 2211a4c..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemory.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.mem;
-
-import java.util.List;
-
-/**
- *
- */
-public class DirectMemory {
-    /** Will be set if  */
-    private boolean restored;
-
-    /** */
-    private List<DirectMemoryRegion> regions;
-
-    /**
-     * @param restored Restored flag.
-     * @param regions Memory fragments.
-     */
-    public DirectMemory(boolean restored, List<DirectMemoryRegion> regions) {
-        this.restored = restored;
-        this.regions = regions;
-    }
-
-    /**
-     * @return Restored flag. If {@code true}, the memory fragments were successfully restored since the previous
-     *      usage and can be reused.
-     */
-    public boolean restored() {
-        return restored;
-    }
-
-    /**
-     * @return Memory fragments.
-     */
-    public List<DirectMemoryRegion> regions() {
-        return regions;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemoryProvider.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemoryProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemoryProvider.java
index 5c73576..a90c6b8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemoryProvider.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/mem/DirectMemoryProvider.java
@@ -18,8 +18,23 @@
 package org.apache.ignite.internal.mem;
 
 /**
- *
+ * Direct memory provider interface. Not thread-safe.
  */
 public interface DirectMemoryProvider {
-    public DirectMemory memory();
+    /**
+     * @param chunkSizes Initializes provider with the chunk sizes.
+     */
+    public void initialize(long[] chunkSizes);
+
+    /**
+     * Shuts down the provider. Will deallocate all previously allocated regions.
+     */
+    public void shutdown();
+
+    /**
+     * Attempts to allocate next memory region. Will return {@code null} if no more regions are available.
+     *
+     * @return Next memory region.
+     */
+    public DirectMemoryRegion nextRegion();
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFileMemoryProvider.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFileMemoryProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFileMemoryProvider.java
index d442baf..b0d8d9a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFileMemoryProvider.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/mem/file/MappedFileMemoryProvider.java
@@ -22,18 +22,17 @@ import java.io.FilenameFilter;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Comparator;
 import java.util.List;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.internal.mem.DirectMemory;
 import org.apache.ignite.internal.mem.DirectMemoryProvider;
-import org.apache.ignite.lifecycle.LifecycleAware;
+import org.apache.ignite.internal.mem.DirectMemoryRegion;
+import org.apache.ignite.internal.util.typedef.internal.U;
 
 /**
  *
  */
-public class MappedFileMemoryProvider implements DirectMemoryProvider, LifecycleAware {
+public class MappedFileMemoryProvider implements DirectMemoryProvider {
     /** */
     private static final String ALLOCATOR_FILE_PREFIX = "allocator-";
 
@@ -50,33 +49,26 @@ public class MappedFileMemoryProvider implements DirectMemoryProvider, Lifecycle
     /** File allocation path. */
     private final File allocationPath;
 
-    /** Clean flag. If true, existing files will be deleted on start. */
-    private boolean clean;
-
-    /** */
-    private final long[] sizes;
-
     /** */
-    private boolean restored;
+    private long[] sizes;
 
     /** */
     private List<MappedFile> mappedFiles;
 
     /**
      * @param allocationPath Allocation path.
-     * @param clean Clean flag. If true, restore procedure will be ignored even if
-     *      allocation folder contains valid files.
-     * @param sizes Sizes of memory chunks to allocate.
      */
-    public MappedFileMemoryProvider(IgniteLogger log, File allocationPath, boolean clean, long[] sizes) {
+    public MappedFileMemoryProvider(IgniteLogger log, File allocationPath) {
         this.log = log;
         this.allocationPath = allocationPath;
-        this.clean = clean;
-        this.sizes = sizes;
     }
 
     /** {@inheritDoc} */
-    @Override public void start() throws IgniteException {
+    @Override public void initialize(long[] sizes) {
+        this.sizes = sizes;
+
+        mappedFiles = new ArrayList<>(sizes.length);
+
         if (!allocationPath.exists()) {
             if (!allocationPath.mkdirs())
                 throw new IgniteException("Failed to initialize allocation path (make sure directory is " +
@@ -88,107 +80,19 @@ public class MappedFileMemoryProvider implements DirectMemoryProvider, Lifecycle
 
         File[] files = allocationPath.listFiles(ALLOCATOR_FILTER);
 
-        Arrays.sort(files, new Comparator<File>() {
-            /** {@inheritDoc} */
-            @Override public int compare(File o1, File o2) {
-                return o1.getName().compareTo(o2.getName());
-            }
-        });
-
-        if (files.length == sizes.length) {
-            for (int i = 0; i < files.length; i++) {
-                File file = files[i];
-
-                if (file.length() != sizes[i]) {
-                    clean = true;
-
-                    break;
-                }
-            }
-        }
-        else
-            clean = true;
-
-        if (files.length == 0 || clean) {
-            if (files.length != 0) {
-                log.info("Will clean up the following files upon start: " + Arrays.asList(files));
-
-                for (File file : files) {
-                    if (!file.delete())
-                        throw new IgniteException("Failed to delete allocated file on start (make sure file is not " +
-                            "opened by another process and current user has enough rights): " + file);
-                }
-            }
-
-            allocateClean();
-
-            return;
-        }
-
-        log.info("Restoring memory state from the files: " + Arrays.asList(files));
+        if (files.length != 0) {
+            log.info("Will clean up the following files upon start: " + Arrays.asList(files));
 
-        mappedFiles = new ArrayList<>(files.length);
-
-        try {
             for (File file : files) {
-                MappedFile mapped = new MappedFile(file, 0);
-
-                mappedFiles.add(mapped);
-            }
-        }
-        catch (IOException e) {
-            // Close all files allocated so far.
-            try {
-                for (MappedFile mapped : mappedFiles)
-                    mapped.close();
-            }
-            catch (IOException e0) {
-                e.addSuppressed(e0);
-            }
-
-            throw new IgniteException(e);
-        }
-
-        restored = true;
-    }
-
-    /**
-     * Allocates clear memory state.
-     */
-    private void allocateClean() {
-        mappedFiles = new ArrayList<>(sizes.length);
-
-        try {
-            int idx = 0;
-
-            for (long size : sizes) {
-                File file = new File(allocationPath, ALLOCATOR_FILE_PREFIX + alignInt(idx));
-
-                MappedFile mappedFile = new MappedFile(file, size);
-
-                mappedFiles.add(mappedFile);
-
-                idx++;
-            }
-        }
-        catch (IOException e) {
-            // Close all files allocated so far.
-            try {
-                for (MappedFile mapped : mappedFiles)
-                    mapped.close();
-            }
-            catch (IOException e0) {
-                e.addSuppressed(e0);
+                if (!file.delete())
+                    throw new IgniteException("Failed to delete allocated file on start (make sure file is not " +
+                        "opened by another process and current user has enough rights): " + file);
             }
-
-            throw new IgniteException(e);
         }
-
-        log.info("Allocated clean memory state at location: " + allocationPath.getAbsolutePath());
     }
 
     /** {@inheritDoc} */
-    @Override public void stop() throws IgniteException {
+    @Override public void shutdown() {
         for (MappedFile file : mappedFiles) {
             try {
                 file.close();
@@ -201,9 +105,28 @@ public class MappedFileMemoryProvider implements DirectMemoryProvider, Lifecycle
     }
 
     /** {@inheritDoc} */
-    @SuppressWarnings("unchecked")
-    @Override public DirectMemory memory() {
-        return new DirectMemory(restored, (List)mappedFiles);
+    @Override public DirectMemoryRegion nextRegion() {
+        try {
+            if (mappedFiles.size() == sizes.length)
+                return null;
+
+            int idx = mappedFiles.size();
+
+            long chunkSize = sizes[idx];
+
+            File file = new File(allocationPath, ALLOCATOR_FILE_PREFIX + alignInt(idx));
+
+            MappedFile mappedFile = new MappedFile(file, chunkSize);
+
+            mappedFiles.add(mappedFile);
+
+            return mappedFile;
+        }
+        catch (IOException e) {
+            U.error(log, "Failed to allocate next memory-mapped region", e);
+
+            return null;
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/mem/unsafe/UnsafeMemoryProvider.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/mem/unsafe/UnsafeMemoryProvider.java b/modules/core/src/main/java/org/apache/ignite/internal/mem/unsafe/UnsafeMemoryProvider.java
index 4cdecde..ef101d0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/mem/unsafe/UnsafeMemoryProvider.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/mem/unsafe/UnsafeMemoryProvider.java
@@ -20,70 +20,71 @@ package org.apache.ignite.internal.mem.unsafe;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.internal.mem.DirectMemory;
-import org.apache.ignite.internal.mem.DirectMemoryRegion;
+import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.mem.DirectMemoryProvider;
+import org.apache.ignite.internal.mem.DirectMemoryRegion;
 import org.apache.ignite.internal.mem.UnsafeChunk;
 import org.apache.ignite.internal.util.GridUnsafe;
-import org.apache.ignite.lifecycle.LifecycleAware;
+import org.apache.ignite.internal.util.typedef.internal.U;
 
 /**
  *
  */
-public class UnsafeMemoryProvider implements DirectMemoryProvider, LifecycleAware {
+public class UnsafeMemoryProvider implements DirectMemoryProvider {
     /** */
-    private final long[] sizes;
+    private long[] sizes;
 
     /** */
     private List<DirectMemoryRegion> regions;
 
+    /** */
+    private IgniteLogger log;
+
     /**
-     * @param sizes Sizes of segments.
+     * @param log Ignite logger to use.
      */
-    public UnsafeMemoryProvider(long[] sizes) {
-        this.sizes = sizes;
+    public UnsafeMemoryProvider(IgniteLogger log) {
+        this.log = log;
     }
 
     /** {@inheritDoc} */
-    @Override public DirectMemory memory() {
-        return new DirectMemory(false, regions);
+    @Override public void initialize(long[] sizes) {
+        this.sizes = sizes;
+
+        regions = new ArrayList<>();
     }
 
     /** {@inheritDoc} */
-    @Override public void start() throws IgniteException {
-        regions = new ArrayList<>();
+    @Override public void shutdown() {
+        for (Iterator<DirectMemoryRegion> it = regions.iterator(); it.hasNext(); ) {
+            DirectMemoryRegion chunk = it.next();
 
-        long allocated = 0;
+            GridUnsafe.freeMemory(chunk.address());
 
-        for (long size : sizes) {
-            long ptr = GridUnsafe.allocateMemory(size);
+            // Safety.
+            it.remove();
+        }
+    }
 
-            if (ptr <= 0) {
-                for (DirectMemoryRegion region : regions)
-                    GridUnsafe.freeMemory(region.address());
+    /** {@inheritDoc} */
+    @Override public DirectMemoryRegion nextRegion() {
+        if (regions.size() == sizes.length)
+            return null;
 
-                throw new IgniteException("Failed to allocate memory [allocated=" + allocated +
-                    ", requested=" + size + ']');
-            }
+        long chunkSize = sizes[regions.size()];
 
-            DirectMemoryRegion chunk = new UnsafeChunk(ptr, size);
+        long ptr = GridUnsafe.allocateMemory(chunkSize);
 
-            regions.add(chunk);
+        if (ptr <= 0) {
+            U.error(log, "Failed to allocate next memory chunk: " + U.readableSize(chunkSize, true));
 
-            allocated += size;
+            return null;
         }
-    }
 
-    /** {@inheritDoc} */
-    @Override public void stop() throws IgniteException {
-        for (Iterator<DirectMemoryRegion> it = regions.iterator(); it.hasNext(); ) {
-            DirectMemoryRegion chunk = it.next();
+        DirectMemoryRegion region = new UnsafeChunk(ptr, chunkSize);
 
-            GridUnsafe.freeMemory(chunk.address());
+        regions.add(region);
 
-            // Safety.
-            it.remove();
-        }
+        return region;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
index 872e496..1d968c5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/impl/PageMemoryNoStoreImpl.java
@@ -20,12 +20,13 @@ package org.apache.ignite.internal.pagemem.impl;
 import java.io.Closeable;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.configuration.MemoryPolicyConfiguration;
-import org.apache.ignite.internal.mem.DirectMemory;
 import org.apache.ignite.internal.mem.DirectMemoryProvider;
 import org.apache.ignite.internal.mem.DirectMemoryRegion;
 import org.apache.ignite.internal.mem.IgniteOutOfMemoryException;
@@ -38,7 +39,6 @@ import org.apache.ignite.internal.util.GridUnsafe;
 import org.apache.ignite.internal.util.OffheapReadWriteLock;
 import org.apache.ignite.internal.util.offheap.GridOffHeapOutOfMemoryException;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lifecycle.LifecycleAware;
 
 import static org.apache.ignite.internal.util.GridUnsafe.wrapPointer;
 
@@ -98,6 +98,21 @@ public class PageMemoryNoStoreImpl implements PageMemory {
      */
     public static final int PAGE_OVERHEAD = LOCK_OFFSET + OffheapReadWriteLock.LOCK_SIZE;
 
+    /** Number of bits required to store segment index. */
+    private static final int SEG_BITS = 4;
+
+    /** Number of bits required to store segment index. */
+    private static final int SEG_CNT = (1 << SEG_BITS);
+
+    /** Number of bits left to store page index. */
+    private static final int IDX_BITS = PageIdUtils.PAGE_IDX_SIZE - SEG_BITS;
+
+    /** Segment mask. */
+    private static final int SEG_MASK = ~(-1 << SEG_BITS);
+
+    /** Index mask. */
+    private static final int IDX_MASK = ~(-1 << IDX_BITS);
+
     /** Page size. */
     private int sysPageSize;
 
@@ -113,20 +128,14 @@ public class PageMemoryNoStoreImpl implements PageMemory {
     /** Object to collect memory usage metrics. */
     private final MemoryMetricsImpl memMetrics;
 
-    /** Segments array. */
-    private Segment[] segments;
-
-    /** Number of bits required to store segment index. */
-    private int segBits;
-
-    /** Number of bits left to store page index. */
-    private int idxBits;
-
     /** */
-    private int segMask;
+    private AtomicLong freePageListHead = new AtomicLong(INVALID_REL_PTR);
+
+    /** Segments array. */
+    private volatile Segment[] segments;
 
     /** */
-    private int idxMask;
+    private final AtomicInteger allocatedPages = new AtomicInteger();
 
     /** */
     private AtomicInteger selector = new AtomicInteger();
@@ -135,6 +144,9 @@ public class PageMemoryNoStoreImpl implements PageMemory {
     private OffheapReadWriteLock rwLock;
 
     /** */
+    private final int totalPages;
+
+    /** */
     private final boolean trackAcquiredPages;
 
     /**
@@ -168,35 +180,46 @@ public class PageMemoryNoStoreImpl implements PageMemory {
 
         assert sysPageSize % 8 == 0 : sysPageSize;
 
+        totalPages = (int)(memPlcCfg.getMaxSize() / sysPageSize);
+
         // TODO configure concurrency level.
         rwLock = new OffheapReadWriteLock(128);
     }
 
     /** {@inheritDoc} */
     @Override public void start() throws IgniteException {
-        if (directMemoryProvider instanceof LifecycleAware)
-            ((LifecycleAware)directMemoryProvider).start();
+        long startSize = memoryPolicyCfg.getInitialSize();
+        long maxSize = memoryPolicyCfg.getMaxSize();
 
-        DirectMemory memory = directMemoryProvider.memory();
+        long[] chunks = new long[SEG_CNT];
 
-        segments = new Segment[memory.regions().size()];
+        chunks[0] = startSize;
 
-        for (int i = 0; i < segments.length; i++) {
-            segments[i] = new Segment(i, memory.regions().get(i));
+        long total = startSize;
 
-            segments[i].init();
-        }
+        long allocChunkSize = Math.max((maxSize - startSize) / (SEG_CNT - 1), 256 * 1024 * 1024);
+
+        int lastIdx = 0;
 
-        segBits = Integer.SIZE - Integer.numberOfLeadingZeros(segments.length - 1);
+        for (int i = 1; i < SEG_CNT; i++) {
+            long allocSize = Math.min(allocChunkSize, maxSize - total);
 
-        // Reserve at least one bit for segment.
-        if (segBits == 0)
-            segBits = 1;
+            if (allocSize <= 0)
+                break;
+
+            chunks[i] = allocSize;
+
+            total += allocSize;
+
+            lastIdx = i;
+        }
+
+        if (lastIdx != SEG_CNT - 1)
+            chunks = Arrays.copyOf(chunks, lastIdx + 1);
 
-        idxBits = PageIdUtils.PAGE_IDX_SIZE - segBits;
+        directMemoryProvider.initialize(chunks);
 
-        segMask = ~(-1 << segBits);
-        idxMask = ~(-1 << idxBits);
+        addSegment(null);
     }
 
     /** {@inheritDoc} */
@@ -205,8 +228,7 @@ public class PageMemoryNoStoreImpl implements PageMemory {
         if (log.isDebugEnabled())
             log.debug("Stopping page memory.");
 
-        if (directMemoryProvider instanceof LifecycleAware)
-            ((LifecycleAware)directMemoryProvider).stop();
+        directMemoryProvider.shutdown();
 
         if (directMemoryProvider instanceof Closeable) {
             try {
@@ -227,35 +249,34 @@ public class PageMemoryNoStoreImpl implements PageMemory {
     @Override public long allocatePage(int cacheId, int partId, byte flags) {
         memMetrics.incrementTotalAllocatedPages();
 
-        long relPtr = INVALID_REL_PTR;
+        long relPtr = borrowFreePage();
         long absPtr = 0;
 
-        for (Segment seg : segments) {
-            relPtr = seg.borrowFreePage();
+        if (relPtr != INVALID_REL_PTR) {
+            int pageIdx = PageIdUtils.pageIndex(relPtr);
 
-            if (relPtr != INVALID_REL_PTR) {
-                absPtr = seg.absolute(PageIdUtils.pageIndex(relPtr));
+            Segment seg = segment(pageIdx);
 
-                break;
-            }
+            absPtr = seg.absolute(pageIdx);
         }
 
         // No segments contained a free page.
         if (relPtr == INVALID_REL_PTR) {
-            int segAllocIdx = nextRoundRobinIndex();
-
-            for (int i = 0; i < segments.length; i++) {
-                int idx = (segAllocIdx + i) % segments.length;
-
-                Segment seg = segments[idx];
+            Segment[] seg0 = segments;
+            Segment allocSeg = seg0[seg0.length - 1];
 
-                relPtr = seg.allocateFreePage(flags);
+            while (allocSeg != null) {
+                relPtr = allocSeg.allocateFreePage(flags);
 
                 if (relPtr != INVALID_REL_PTR) {
-                    absPtr = seg.absolute(PageIdUtils.pageIndex(relPtr));
+                    if (relPtr != INVALID_REL_PTR) {
+                        absPtr = allocSeg.absolute(PageIdUtils.pageIndex(relPtr));
 
-                    break;
+                        break;
+                    }
                 }
+                else
+                    allocSeg = addSegment(seg0);
             }
         }
 
@@ -263,7 +284,7 @@ public class PageMemoryNoStoreImpl implements PageMemory {
             throw new IgniteOutOfMemoryException("Not enough memory allocated " +
                 "(consider increasing memory policy size or enabling evictions) " +
                 "[policyName=" + memoryPolicyCfg.getName() +
-                ", size=" + U.readableSize(memoryPolicyCfg.getSize(), true) + "]"
+                ", size=" + U.readableSize(memoryPolicyCfg.getMaxSize(), true) + "]"
             );
 
         assert (relPtr & ~PageIdUtils.PAGE_IDX_MASK) == 0;
@@ -281,9 +302,7 @@ public class PageMemoryNoStoreImpl implements PageMemory {
 
     /** {@inheritDoc} */
     @Override public boolean freePage(int cacheId, long pageId) {
-        Segment seg = segment(PageIdUtils.pageIndex(pageId));
-
-        seg.releaseFreePage(pageId);
+        releaseFreePage(pageId);
 
         return true;
     }
@@ -334,6 +353,13 @@ public class PageMemoryNoStoreImpl implements PageMemory {
     }
 
     /**
+     * @return Total number of pages may be allocated for this instance.
+     */
+    public int totalPages() {
+        return totalPages;
+    }
+
+    /**
      * @return Total number of acquired pages.
      */
     public long acquiredPages() {
@@ -382,7 +408,7 @@ public class PageMemoryNoStoreImpl implements PageMemory {
      * @return Segment index.
      */
     private int segmentIndex(long pageIdx) {
-        return (int)((pageIdx >> idxBits) & segMask);
+        return (int)((pageIdx >> IDX_BITS) & SEG_MASK);
     }
 
     /**
@@ -393,8 +419,8 @@ public class PageMemoryNoStoreImpl implements PageMemory {
     private long fromSegmentIndex(int segIdx, long pageIdx) {
         long res = 0;
 
-        res = (res << segBits) | (segIdx & segMask);
-        res = (res << idxBits) | (pageIdx & idxMask);
+        res = (res << SEG_BITS) | (segIdx & SEG_MASK);
+        res = (res << IDX_BITS) | (pageIdx & IDX_MASK);
 
         return res;
     }
@@ -428,7 +454,7 @@ public class PageMemoryNoStoreImpl implements PageMemory {
     }
 
     /** {@inheritDoc} */
-    public long readLockForce(int cacheId, long pageId, long page) {
+    @Override public long readLockForce(int cacheId, long pageId, long page) {
         if (rwLock.readLock(page + LOCK_OFFSET, -1))
             return page + PAGE_OVERHEAD;
 
@@ -457,19 +483,169 @@ public class PageMemoryNoStoreImpl implements PageMemory {
     }
 
     /** {@inheritDoc} */
-    @Override public void writeUnlock(int cacheId, long pageId, long page,
+    @Override public void writeUnlock(
+        int cacheId,
+        long pageId,
+        long page,
         Boolean walPlc,
-        boolean dirtyFlag) {
+        boolean dirtyFlag
+    ) {
         long actualId = PageIO.getPageId(page + PAGE_OVERHEAD);
+
         rwLock.writeUnlock(page + LOCK_OFFSET, PageIdUtils.tag(actualId));
     }
 
+    /** {@inheritDoc} */
     @Override public boolean isDirty(int cacheId, long pageId, long page) {
         // always false for page no store.
         return false;
     }
 
     /**
+     * @param pageIdx Page index.
+     * @return Total page sequence number.
+     */
+    public int pageSequenceNumber(int pageIdx) {
+        Segment seg = segment(pageIdx);
+
+        return seg.sequenceNumber(pageIdx);
+    }
+
+    /**
+     * @param seqNo Page sequence number.
+     * @return Page index.
+     */
+    public int pageIndex(int seqNo) {
+        Segment[] segs = segments;
+
+        int low = 0, high = segs.length - 1;
+
+        while (low <= high) {
+            int mid = (low + high) >>> 1;
+
+            Segment seg = segs[mid];
+
+            int cmp = seg.containsPageBySequence(seqNo);
+
+            if (cmp < 0)
+                high = mid - 1;
+            else if (cmp > 0) {
+                low = mid + 1;
+            }
+            else
+                return seg.pageIndex(seqNo);
+        }
+
+        throw new IgniteException("Allocated page must always be present in one of the segments [seqNo=" + seqNo +
+            ", segments=" + Arrays.toString(segs) + ']');
+    }
+
+    /**
+     * @param pageId Page ID to release.
+     */
+    private void releaseFreePage(long pageId) {
+        int pageIdx = PageIdUtils.pageIndex(pageId);
+
+        // Clear out flags and file ID.
+        long relPtr = PageIdUtils.pageId(0, (byte)0, pageIdx);
+
+        Segment seg = segment(pageIdx);
+
+        long absPtr = seg.absolute(pageIdx);
+
+        // Second, write clean relative pointer instead of page ID.
+        writePageId(absPtr, relPtr);
+
+        // Third, link the free page.
+        while (true) {
+            long freePageRelPtrMasked = freePageListHead.get();
+
+            long freePageRelPtr = freePageRelPtrMasked & RELATIVE_PTR_MASK;
+
+            GridUnsafe.putLong(absPtr, freePageRelPtr);
+
+            if (freePageListHead.compareAndSet(freePageRelPtrMasked, relPtr)) {
+                allocatedPages.decrementAndGet();
+
+                return;
+            }
+        }
+    }
+
+    /**
+     * @return Relative pointer to a free page that was borrowed from the allocated pool.
+     */
+    private long borrowFreePage() {
+        while (true) {
+            long freePageRelPtrMasked = freePageListHead.get();
+
+            long freePageRelPtr = freePageRelPtrMasked & ADDRESS_MASK;
+
+            if (freePageRelPtr != INVALID_REL_PTR) {
+                int pageIdx = PageIdUtils.pageIndex(freePageRelPtr);
+
+                Segment seg = segment(pageIdx);
+
+                long freePageAbsPtr = seg.absolute(pageIdx);
+                long nextFreePageRelPtr = GridUnsafe.getLong(freePageAbsPtr) & ADDRESS_MASK;
+                long cnt = ((freePageRelPtrMasked & COUNTER_MASK) + COUNTER_INC) & COUNTER_MASK;
+
+                if (freePageListHead.compareAndSet(freePageRelPtrMasked, nextFreePageRelPtr | cnt)) {
+                    GridUnsafe.putLong(freePageAbsPtr, PAGE_MARKER);
+
+                    allocatedPages.incrementAndGet();
+
+                    return freePageRelPtr;
+                }
+            }
+            else
+                return INVALID_REL_PTR;
+        }
+    }
+
+    /**
+     * Attempts to add a new memory segment.
+     *
+     * @param oldRef Old segments array. If this method observes another segments array, it will allocate a new
+     *      segment (if possible). If the array has already been updated, it will return the last element in the
+     *      new array.
+     * @return Added segment, if successfull, {@code null} if failed to add.
+     */
+    private synchronized Segment addSegment(Segment[] oldRef) {
+        if (segments == oldRef) {
+            DirectMemoryRegion region = directMemoryProvider.nextRegion();
+
+            // No more memory is available.
+            if (region == null)
+                return null;
+
+            if (oldRef != null) {
+                if (log.isInfoEnabled())
+                    log.info("Allocated next memory segment [plcName=" + memoryPolicyCfg.getName() +
+                        ", chunkSize=" + U.readableSize(region.size(), true) + ']');
+            }
+
+            Segment[] newRef = new Segment[oldRef == null ? 1 : oldRef.length + 1];
+
+            if (oldRef != null)
+                System.arraycopy(oldRef, 0, newRef, 0, oldRef.length);
+
+            Segment lastSeg = oldRef == null ? null : oldRef[oldRef.length - 1];
+
+            Segment allocated = new Segment(newRef.length - 1, region, lastSeg == null ? 0 : lastSeg.sumPages());
+
+            allocated.init();
+
+            newRef[newRef.length - 1] = allocated;
+
+            segments = newRef;
+        }
+
+        // Only this synchronized method writes to segments, so it is safe to read twice.
+        return segments[segments.length - 1];
+    }
+
+    /**
      *
      */
     private class Segment extends ReentrantReadWriteLock {
@@ -482,9 +658,6 @@ public class PageMemoryNoStoreImpl implements PageMemory {
         /** Direct memory chunk. */
         private DirectMemoryRegion region;
 
-        /** Pointer to the address of the free page list. */
-        private long freePageListPtr;
-
         /** Last allocated page index. */
         private long lastAllocatedIdxPtr;
 
@@ -492,7 +665,10 @@ public class PageMemoryNoStoreImpl implements PageMemory {
         private long pagesBase;
 
         /** */
-        private final AtomicInteger allocatedPages;
+        private int pagesInPrevSegments;
+
+        /** */
+        private int maxPages;
 
         /** */
         private final AtomicInteger acquiredPages;
@@ -500,12 +676,13 @@ public class PageMemoryNoStoreImpl implements PageMemory {
         /**
          * @param idx Index.
          * @param region Memory region to use.
+         * @param pagesInPrevSegments Number of pages in previously allocated segments.
          */
-        private Segment(int idx, DirectMemoryRegion region) {
+        private Segment(int idx, DirectMemoryRegion region, int pagesInPrevSegments) {
             this.idx = idx;
             this.region = region;
+            this.pagesInPrevSegments = pagesInPrevSegments;
 
-            allocatedPages = new AtomicInteger();
             acquiredPages = new AtomicInteger();
         }
 
@@ -515,10 +692,6 @@ public class PageMemoryNoStoreImpl implements PageMemory {
         private void init() {
             long base = region.address();
 
-            freePageListPtr = base;
-
-            base += 8;
-
             lastAllocatedIdxPtr = base;
 
             base += 8;
@@ -526,8 +699,11 @@ public class PageMemoryNoStoreImpl implements PageMemory {
             // Align by 8 bytes.
             pagesBase = (base + 7) & ~0x7;
 
-            GridUnsafe.putLong(freePageListPtr, INVALID_REL_PTR);
             GridUnsafe.putLong(lastAllocatedIdxPtr, 0);
+
+            long limit = region.address() + region.size();
+
+            maxPages = (int)((limit - pagesBase) / sysPageSize);
         }
 
         /**
@@ -556,7 +732,7 @@ public class PageMemoryNoStoreImpl implements PageMemory {
          * @return Absolute pointer.
          */
         private long absolute(int pageIdx) {
-            pageIdx &= idxMask;
+            pageIdx &= IDX_MASK;
 
             long off = ((long)pageIdx) * sysPageSize;
 
@@ -564,75 +740,34 @@ public class PageMemoryNoStoreImpl implements PageMemory {
         }
 
         /**
-         * @return Total number of loaded pages for the segment.
+         * @param pageIdx Page index with encoded segment.
+         * @return Absolute page sequence number.
          */
-        private int allocatedPages() {
-            return allocatedPages.get();
+        private int sequenceNumber(int pageIdx) {
+            pageIdx &= IDX_MASK;
+
+            return pagesInPrevSegments + pageIdx;
         }
 
         /**
-         * @return Total number of currently acquired pages.
+         * @return Page sequence number upper bound.
          */
-        private int acquiredPages() {
-            return acquiredPages.get();
+        private int sumPages() {
+            return pagesInPrevSegments + maxPages;
         }
 
         /**
-         * @param pageId Page ID to release.
+         * @return Total number of loaded pages for the segment.
          */
-        private void releaseFreePage(long pageId) {
-            int pageIdx = PageIdUtils.pageIndex(pageId);
-
-            // Clear out flags and file ID.
-            long relPtr = PageIdUtils.pageId(0, (byte)0, pageIdx);
-
-            long absPtr = absolute(pageIdx);
-
-            // Second, write clean relative pointer instead of page ID.
-            writePageId(absPtr, relPtr);
-
-            // Third, link the free page.
-            while (true) {
-                long freePageRelPtrMasked = GridUnsafe.getLong(freePageListPtr);
-
-                long freePageRelPtr = freePageRelPtrMasked & RELATIVE_PTR_MASK;
-
-                GridUnsafe.putLong(absPtr, freePageRelPtr);
-
-                if (GridUnsafe.compareAndSwapLong(null, freePageListPtr, freePageRelPtrMasked, relPtr)) {
-                    allocatedPages.decrementAndGet();
-
-                    return;
-                }
-            }
+        private int allocatedPages() {
+            return allocatedPages.get();
         }
 
         /**
-         * @return Relative pointer to a free page that was borrowed from the allocated pool.
+         * @return Total number of currently acquired pages.
          */
-        private long borrowFreePage() {
-            while (true) {
-                long freePageRelPtrMasked = GridUnsafe.getLong(freePageListPtr);
-
-                long freePageRelPtr = freePageRelPtrMasked & ADDRESS_MASK;
-                long cnt = ((freePageRelPtrMasked & COUNTER_MASK) + COUNTER_INC) & COUNTER_MASK;
-
-                if (freePageRelPtr != INVALID_REL_PTR) {
-                    long freePageAbsPtr = absolute(PageIdUtils.pageIndex(freePageRelPtr));
-
-                    long nextFreePageRelPtr = GridUnsafe.getLong(freePageAbsPtr) & ADDRESS_MASK;
-
-                    if (GridUnsafe.compareAndSwapLong(null, freePageListPtr, freePageRelPtrMasked, nextFreePageRelPtr | cnt)) {
-                        GridUnsafe.putLong(freePageAbsPtr, PAGE_MARKER);
-
-                        allocatedPages.incrementAndGet();
-
-                        return freePageRelPtr;
-                    }
-                }
-                else
-                    return INVALID_REL_PTR;
-            }
+        private int acquiredPages() {
+            return acquiredPages.get();
         }
 
         /**
@@ -644,7 +779,7 @@ public class PageMemoryNoStoreImpl implements PageMemory {
             long limit = region.address() + region.size();
 
             while (true) {
-                long lastIdx = GridUnsafe.getLong(lastAllocatedIdxPtr);
+                long lastIdx = GridUnsafe.getLongVolatile(null, lastAllocatedIdxPtr);
 
                 // Check if we have enough space to allocate a page.
                 if (pagesBase + (lastIdx + 1) * sysPageSize > limit)
@@ -671,5 +806,28 @@ public class PageMemoryNoStoreImpl implements PageMemory {
                 }
             }
         }
+
+        /**
+         * @param seqNo Page sequence number.
+         * @return {@code 0} if this segment contains the page with the given sequence number,
+         *      {@code -1} if one of the previous segments contains the page with the given sequence number,
+         *      {@code 1} if one of the next segments contains the page with the given sequence number.
+         */
+        public int containsPageBySequence(int seqNo) {
+            if (seqNo < pagesInPrevSegments)
+                return -1;
+            else if (seqNo < pagesInPrevSegments + maxPages)
+                return 0;
+            else
+                return 1;
+        }
+
+        /**
+         * @param seqNo Page sequence number.
+         * @return Page index
+         */
+        public int pageIndex(int seqNo) {
+            return PageIdUtils.pageIndex(fromSegmentIndex(idx, seqNo - pagesInPrevSegments));
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
index c633fde..deaaac0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheClusterMetricsMXBeanImpl.java
@@ -104,11 +104,6 @@ class CacheClusterMetricsMXBeanImpl implements CacheMetricsMXBean {
     }
 
     /** {@inheritDoc} */
-    @Override public long getOffHeapMaxSize() {
-        return cache.clusterMetrics().getOffHeapMaxSize();
-    }
-
-    /** {@inheritDoc} */
     @Override public int getSize() {
         return cache.clusterMetrics().getSize();
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheLocalMetricsMXBeanImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheLocalMetricsMXBeanImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheLocalMetricsMXBeanImpl.java
index cdab58a..0fb7568 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheLocalMetricsMXBeanImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheLocalMetricsMXBeanImpl.java
@@ -104,11 +104,6 @@ class CacheLocalMetricsMXBeanImpl implements CacheMetricsMXBean {
     }
 
     /** {@inheritDoc} */
-    @Override public long getOffHeapMaxSize() {
-        return cache.metrics0().getOffHeapMaxSize();
-    }
-
-    /** {@inheritDoc} */
     @Override public int getSize() {
         return cache.metrics0().getSize();
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
index 1d03e64..d4ad8e4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
@@ -220,11 +220,6 @@ public class CacheMetricsImpl implements CacheMetrics {
     }
 
     /** {@inheritDoc} */
-    @Override public long getOffHeapMaxSize() {
-        return 0;
-    }
-
-    /** {@inheritDoc} */
     @Override public int getSize() {
         GridCacheAdapter<?, ?> cache = cctx.cache();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/11c23b62/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java
index a8d7693..67f646a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsSnapshot.java
@@ -104,9 +104,6 @@ public class CacheMetricsSnapshot implements CacheMetrics, Externalizable {
     /** Memory size allocated in off-heap. */
     private long offHeapAllocatedSize;
 
-    /** Off-heap memory maximum size*/
-    private long offHeapMaxSize;
-
     /** Number of non-{@code null} values in the cache. */
     private int size;
 
@@ -249,7 +246,6 @@ public class CacheMetricsSnapshot implements CacheMetrics, Externalizable {
         offHeapPrimaryEntriesCnt = m.getOffHeapPrimaryEntriesCount();
         offHeapBackupEntriesCnt = m.getOffHeapBackupEntriesCount();
         offHeapAllocatedSize = m.getOffHeapAllocatedSize();
-        offHeapMaxSize = m.getOffHeapMaxSize();
 
         size = m.getSize();
         keySize = m.getKeySize();
@@ -314,8 +310,6 @@ public class CacheMetricsSnapshot implements CacheMetrics, Externalizable {
         isReadThrough = loc.isReadThrough();
         isWriteThrough = loc.isWriteThrough();
 
-        offHeapMaxSize = loc.getOffHeapMaxSize();
-
         for (CacheMetrics e : metrics) {
             reads += e.getCacheGets();
             puts += e.getCachePuts();
@@ -570,11 +564,6 @@ public class CacheMetricsSnapshot implements CacheMetrics, Externalizable {
     }
 
     /** {@inheritDoc} */
-    @Override public long getOffHeapMaxSize() {
-        return offHeapMaxSize;
-    }
-
-    /** {@inheritDoc} */
     @Override public int getSize() {
         return size;
     }
@@ -776,7 +765,6 @@ public class CacheMetricsSnapshot implements CacheMetrics, Externalizable {
         out.writeLong(offHeapPrimaryEntriesCnt);
         out.writeLong(offHeapBackupEntriesCnt);
         out.writeLong(offHeapAllocatedSize);
-        out.writeLong(offHeapMaxSize);
 
         out.writeInt(dhtEvictQueueCurrSize);
         out.writeInt(txThreadMapSize);
@@ -825,7 +813,6 @@ public class CacheMetricsSnapshot implements CacheMetrics, Externalizable {
         offHeapPrimaryEntriesCnt = in.readLong();
         offHeapBackupEntriesCnt = in.readLong();
         offHeapAllocatedSize = in.readLong();
-        offHeapMaxSize = in.readLong();
 
         dhtEvictQueueCurrSize = in.readInt();
         txThreadMapSize = in.readInt();