簡體   English   中英

Neo4j Java API:運行多個查詢后,超出了GC開銷限制

[英]Neo4j Java API: GC overhead limit exceeded after running multiple queries

我在Java中使用Neo4j 2.3.0 我有16 GB RAM,使用“ -Xmx12g -Xms12g ”作為VM參數在MAC OSX Laptop上運行代碼。

我在Neo4j Java API中遇到了“超出了GC開銷限制”的問題。

為了進行大量查詢的實驗,我有一個程序可以在不同的query.db上打開事務,並從包裝在對象中的我自己的框架中獲得答案(它運行一個查詢並在其中打印其運行時間。一份文件)。

因此,為了運行查詢,我不使用Cypher

對於每個查詢,我在query.db和data.db上打開兩個事務 ,初始化我的框架並運行它。 內存使用量略有增加,並且最終發生了“ GC開銷”。

try (Transaction txG = knowledgeGraph.beginTx()) {
     try (Transaction txQ = queryGraph.beginTx()) {
          MyObj myFramework = new MyObj();
          printTheResultsIntoTheFile(framework.run());
          myFramework =null;
          txQ.success();
          txQ.close();

這些是我消除此錯誤的一些嘗試:

  1. 使用監控程序轉儲堆之后,我發現此“ org.neo4j.io.pagecache.impl.muninn.MuninnPageCache ”存在一些問題,因此,我嘗試設置頁面緩存大小並將其限制為較小的值:

    dataGraph = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(MODELGRAPH_DB_PATH) .setConfig(GraphDatabaseSettings.pagecache_memory, "500M").newGraphDatabase();

但是,仍然存在“內存泄漏”問題。

  1. tx.success() ,我調用了tx.close()來確保它不使用內存。

  2. 使用框架(對象)查找查詢的答案后,我將其顯式設置為null。 topkFramework=null;

  3. 我叫System.gc(); System.runFinalization();

  4. 我將所有靜態變量(如MyCacheServer或MyNeighborIndexer)更改為非靜態變量,並在每個查詢中將其清除,並將其顯式設置為null。

    queryNodeIdSet.clear(); queryNodeIdSet = null; queryNodeIdSet = new HashSet<Long>();

在深入研究Neo4j之后,我發現它與一個接一個地創建許多查詢圖有關。 盡管我在處理每個查詢后都調用了db.shutdown(),但似乎緩存不會為空。

smallGraph = new GraphDatabaseFactory().newEmbeddedDatabaseBuilder(graphPath)
            .setConfig(GraphDatabaseSettings.pagecache_memory, "240k").newGraphDatabase();

我已添加此配置並將其設置為最小可能的數量。 現在,內存泄漏不足以破壞我的進程。 運行約1000個查詢后,它仍在運行。 在運行200個查詢后,它消耗了我的所有內存(12 GB)。

這是我的堆棧跟蹤:

Caused by: java.lang.OutOfMemoryError: GC overhead limit exceeded

    at org.neo4j.io.pagecache.impl.muninn.MuninnPageCache.<init>(MuninnPageCache.java:246)

    at org.neo4j.kernel.impl.pagecache.ConfiguringPageCacheFactory.createPageCache(ConfiguringPageCacheFactory.java:96)

    at org.neo4j.kernel.impl.pagecache.ConfiguringPageCacheFactory.getOrCreatePageCache(ConfiguringPageCacheFactory.java:87)

    at org.neo4j.kernel.impl.factory.PlatformModule.createPageCache(PlatformModule.java:277)

    at org.neo4j.kernel.impl.factory.PlatformModule.<init>(PlatformModule.java:154)

    at org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.createPlatform(GraphDatabaseFacadeFactory.java:181)

    at org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.newFacade(GraphDatabaseFacadeFactory.java:124)

    at org.neo4j.kernel.impl.factory.CommunityFacadeFactory.newFacade(CommunityFacadeFactory.java:43)

    at org.neo4j.kernel.impl.factory.GraphDatabaseFacadeFactory.newFacade(GraphDatabaseFacadeFactory.java:108)

    at org.neo4j.graphdb.factory.GraphDatabaseFactory.newDatabase(GraphDatabaseFactory.java:129)

    at org.neo4j.graphdb.factory.GraphDatabaseFactory$1.newDatabase(GraphDatabaseFactory.java:117)

    at org.neo4j.graphdb.factory.GraphDatabaseBuilder.newGraphDatabase(GraphDatabaseBuilder.java:185)

    at org.neo4j.graphdb.factory.GraphDatabaseFactory.newEmbeddedDatabase(GraphDatabaseFactory.java:79)

    at org.neo4j.graphdb.factory.GraphDatabaseFactory.newEmbeddedDatabase(GraphDatabaseFactory.java:74)

這是一個猜測(現在沒有時間嘗試),但我會嘗試一下。 Neo4j不支持嵌套事務。 任何頂級事務(在您的情況下為txG )都綁定到ThreadLocal 任何“嵌套”交易( txQ )成為PlaceboTransaction 因此,在其上調用success()close()均無效。

因此,在頂層事務處於打開狀態時,您在子事務中訪問的所有內容都會保存在內存(堆)中,直到頂層事務完成為止。 我知道這是兩個不同的數據庫,但是仍然是ThreadLocal

我認為您也應該在每次關閉子級子時也嘗試關閉頂級子級。 看看是否有幫助。

通常,每個JVM實例僅使用一個Neo4j實例。

不幸的是,直到JVM關閉,才會釋放堆外頁面緩存。

對於與堆相關的部分,您必須確保在調用System.gc()之前,已調用shutdown和null-out引用。

您可以重用“ smallGraph”,清理實例,例如使用MATCH (n) DETACH DELETE n; 然后重新填充它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM