[ 
https://issues.apache.org/jira/browse/IGNITE-8917?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16718685#comment-16718685
 ] 

Semen Boikov commented on IGNITE-8917:
--------------------------------------

For non-atomic caches or when entry is updated on atomic cache backups memory 
is evicted right before single entry is updated, and it works more or less 
reliable (see usages IgniteCacheDatabaseSharedManager.ensureFreeSpace). But now 
putAll operation for atomic cache on primary node calls 
IgniteCacheDatabaseSharedManager.ensureFreeSpace not  before each entry update, 
but only once for putAll. It is implemented this way since putAll first locks 
all entries and then updates each entry, and it is not safe to call 
'ensureFreeSpace' for each entry while entries locks are held (it can cause 
deadlock).

I tried to implement some workaround to predict how much space is needed for 
putAll and evict this amount of pages before putAll, but it does not work 
reliable. First I don't see how to predict how many pages will be needed to 
update BPlustTree and  free lists, also before entry is locked we don't know is 
it will be update or insert + for invoke operation result is now known in 
advance. 

I believe if thread-per-partition is implemented (IGNITE-4682) then it won't be 
necessary to lock all entries before update, and ensureFreeSpace can be called 
right before each entry update.

> IgniteOutOfMemory when performing putAll with configured pageEvictionMode
> -------------------------------------------------------------------------
>
>                 Key: IGNITE-8917
>                 URL: https://issues.apache.org/jira/browse/IGNITE-8917
>             Project: Ignite
>          Issue Type: Bug
>          Components: cache
>    Affects Versions: 2.5
>            Reporter: Denis Mekhanikov
>            Assignee: Semen Boikov
>            Priority: Major
>         Attachments: IgnitePdsPageEvictionBatchTest.java
>
>
> When {{pageEvictionMode}} is configured and {{IgniteCache#putAll(...)}} 
> operations are performed, then page eviction may not be applied properly. It 
> results in IgniteOutOfMemory being thrown.
> PFA test, reproducing the problem.
> Exception:
> {noformat}
> Critical system error detected. Will be handled accordingly to configured 
> handler [hnd=class o.a.i.failure.NoOpFailureHandler, 
> failureCtx=FailureContext [type=CRITICAL_ERROR, err=class 
> o.a.i.i.mem.IgniteOutOfMemoryException: Out of memory in data region 
> [name=evicting-data-region, initSize=256.0 MiB, maxSize=256.0 MiB, 
> persistenceEnabled=false] Try the following:
>  ^-- Increase maximum off-heap memory size (DataRegionConfiguration.maxSize)
>  ^-- Enable Ignite persistence (DataRegionConfiguration.persistenceEnabled)
>  ^-- Enable eviction or expiration policies]]
>  class org.apache.ignite.internal.mem.IgniteOutOfMemoryException: Out of 
> memory in data region [name=evicting-data-region, initSize=256.0 MiB, 
> maxSize=256.0 MiB, persistenceEnabled=false] Try the following:
>  ^-- Increase maximum off-heap memory size (DataRegionConfiguration.maxSize)
>  ^-- Enable Ignite persistence (DataRegionConfiguration.persistenceEnabled)
>  ^-- Enable eviction or expiration policies
>  at 
> org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl.allocatePage(PageMemoryNoStoreImpl.java:305)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.freelist.AbstractFreeList.allocateDataPage(AbstractFreeList.java:464)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.freelist.AbstractFreeList.insertDataRow(AbstractFreeList.java:491)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.RowStore.addRow(RowStore.java:97)
>  at 
> org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManagerImpl$CacheDataStoreImpl.createRow(IgniteCacheOffheapManagerImpl.java:1325)
>  at 
> org.apache.ignite.internal.processors.cache.GridCacheMapEntry$AtomicCacheUpdateClosure.update(GridCacheMapEntry.java:4955)
>  at 
> org.apache.ignite.internal.processors.cache.GridCacheMapEntry$AtomicCacheUpdateClosure.call(GridCacheMapEntry.java:4750)
>  at 
> org.apache.ignite.internal.processors.cache.GridCacheMapEntry$AtomicCacheUpdateClosure.call(GridCacheMapEntry.java:4464)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree$Invoke.invokeClosure(BPlusTree.java:3083)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree$Invoke.access$6200(BPlusTree.java:2977)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree.invokeDown(BPlusTree.java:1726)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree.invokeDown(BPlusTree.java:1703)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree.invoke(BPlusTree.java:1610)
>  at 
> org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManagerImpl$CacheDataStoreImpl.invoke(IgniteCacheOffheapManagerImpl.java:1272)
>  at 
> org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManagerImpl.invoke(IgniteCacheOffheapManagerImpl.java:370)
>  at 
> org.apache.ignite.internal.processors.cache.GridCacheMapEntry.innerUpdate(GridCacheMapEntry.java:1755)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicCache.updateSingle(GridDhtAtomicCache.java:2420)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicCache.update(GridDhtAtomicCache.java:1882)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicCache.updateAllAsyncInternal0(GridDhtAtomicCache.java:1735)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicCache.updateAllAsyncInternal(GridDhtAtomicCache.java:1627)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridNearAtomicAbstractUpdateFuture.sendSingleRequest(GridNearAtomicAbstractUpdateFuture.java:299)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridNearAtomicUpdateFuture.map(GridNearAtomicUpdateFuture.java:812)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridNearAtomicUpdateFuture.mapOnTopology(GridNearAtomicUpdateFuture.java:664)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridNearAtomicAbstractUpdateFuture.map(GridNearAtomicAbstractUpdateFuture.java:248)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicCache.updateAll0(GridDhtAtomicCache.java:1068)
>  at 
> org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicCache.putAll0(GridDhtAtomicCache.java:648)
>  at 
> org.apache.ignite.internal.processors.cache.GridCacheAdapter.putAll(GridCacheAdapter.java:2811)
>  at 
> org.apache.ignite.internal.processors.cache.IgniteCacheProxyImpl.putAll(IgniteCacheProxyImpl.java:1147)
>  at 
> org.apache.ignite.internal.processors.cache.GatewayProtectedCacheProxy.putAll(GatewayProtectedCacheProxy.java:836)
>  at 
> org.apache.ignite.internal.processors.cache.persistence.db.IgnitePdsPageEvictionBatchTest.testPageEvictionPutAll(IgnitePdsPageEvictionBatchTest.java:57)
>  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>  at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
>  at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
>  at java.lang.reflect.Method.invoke(Method.java:498)
>  at junit.framework.TestCase.runTest(TestCase.java:176)
>  at 
> org.apache.ignite.testframework.junits.GridAbstractTest.runTestInternal(GridAbstractTest.java:2086)
>  at 
> org.apache.ignite.testframework.junits.GridAbstractTest.access$000(GridAbstractTest.java:140)
>  at 
> org.apache.ignite.testframework.junits.GridAbstractTest$5.run(GridAbstractTest.java:2001)
>  at java.lang.Thread.run(Thread.java:748){noformat}



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)

Reply via email to