2013-03-21 3 views
1

mapdb를 테스트 할 때 메모리 부족 오류가 발생합니다. 이 프로젝트의 전체 아이디어가 데이터 구조를 디스크에 직렬화하고 메모리 문제를 피하는 것이라면, 나는 잘못된 생각을하고 있습니다. 내가 뭘 잘못하고 있는거야? 아니면 버그가 있습니까?메모리 부족/mapdb

@Test 
    public void testLarge() throws Exception { 
     final HTreeMap<UUID, String> storage = DBMaker.newTempHashMap(); 

     String string = createDataSize(250); 

     ArrayList<UUID> keys = new ArrayList<>(); 
     for (int i = 0; i < 320000; i++) { 
      final UUID key = UUID.randomUUID(); 
      storage.put(key, string); 
      keys.add(key); 
     } 

     for (UUID key : keys) { 
      assertNotNull(storage.get(key)); 
     } 

     for (UUID key : keys) { 
      storage.remove(key); 
     } 

     assertEquals("nothing left", 0, storage.size()); 
    } 

    /** 
    * Creates a message of size @msgSize in KB. 
    */ 
    private static String createDataSize(int msgSize) { 
     // Java chars are 2 bytes 
     msgSize = msgSize/2; 
     msgSize = msgSize * 1024; 
     StringBuilder sb = new StringBuilder(msgSize); 
     for (int i = 0; i < msgSize; i++) { 
      sb.append('a'); 
     } 
     return sb.toString(); 
    } 
} 

스택 추적. 내 함수의 29 행은 "assertNotNull (storage.get (key));"에 해당합니다. 선.

java.lang.OutOfMemoryError: Java heap space 
    at java.util.Arrays.copyOf(Arrays.java:2367) 
    at java.lang.String.<init>(String.java:168) 
    at org.mapdb.SerializerBase.deserializeString(SerializerBase.java:724) 
    at org.mapdb.SerializerBase.deserialize(SerializerBase.java:932) 
    at org.mapdb.SerializerBase.deserialize(SerializerBase.java:731) 
    at org.mapdb.HTreeMap$1.deserialize(HTreeMap.java:134) 
    at org.mapdb.HTreeMap$1.deserialize(HTreeMap.java:123) 
    at org.mapdb.StorageDirect.recordGet2(StorageDirect.java:536) 
    at org.mapdb.StorageDirect.get(StorageDirect.java:201) 
    at org.mapdb.EngineWrapper.get(EngineWrapper.java:50) 
    at org.mapdb.AsyncWriteEngine.get(AsyncWriteEngine.java:163) 
    at org.mapdb.EngineWrapper.get(EngineWrapper.java:50) 
    at org.mapdb.CacheHashTable.get(CacheHashTable.java:85) 
    at org.mapdb.HTreeMap.get(HTreeMap.java:387) 
    at com.sample.StorageTest.testLarge(StorageTest.java:29) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:292) 

난 샘플 작성자의 제안에 따라, 나는 다음과 같이 문제를 수정했다.

diff -r 35918e46551a src/test/java/com/sample/StorageTest.java 
--- a/src/test/java/com/sample/StorageTest.java Thu Mar 21 13:40:16 2013 -0600 
+++ b/src/test/java/com/sample/StorageTest.java Thu Mar 21 13:42:24 2013 -0600 
@@ -16,7 +16,9 @@ 

    @Test 
    public void testLarge() throws Exception { 
-  final HTreeMap<UUID, String> storage = DBMaker.newTempHashMap(); 
+  File tmpFile = File.createTempFile("largeTest", null); 
+  DB db = DBMaker.newFileDB(tmpFile).deleteFilesAfterClose().journalDisable().make(); 
+  final HTreeMap<UUID, String> storage = db.getHashMap("name"); 

     String string = createDataSize(250); 

@@ -25,6 +27,9 @@ 
      final UUID key = UUID.randomUUID(); 
      storage.put(key, string); 
      keys.add(key); 
+   if (i%100==0) { 
+    db.commit(); 
+   } 
     } 

     for (UUID key : keys) { 
+2

스택 트레이스는 'testSmall()'에서 예외가 발생했다고 말합니다. 그 방법은 어디에 있습니까? – unholysampler

+0

작고 더 이상 적합하지 않기 때문에 testLarge로 메소드의 이름을 변경했습니다. 그러나 스택 추적을 얻으려면이를 다시 실행하지 않았습니다. 나는 명확성을 위해 스택 추적을 편집 할 것이다. –

답변

2

문서는 commit() 방법이 있다는 것을 나타낸다.

db.commit(); //persist changes into disk 

testLarge() 결코 commit()를 호출, 그래서 아무것도 아직 지속되지 않았다.

close()도 전화하지 않으므로 다른 테스트로 이동할 때지도가 계속 메모리에 남아있을 수 있습니다.

참고 : 저는 도서관에서 일한 적이 없지만 이것이 가장 좋은 추측입니다.

+0

나를 위해 문서를 읽어 주셔서 감사합니다 :). 나는 그것을 들여다 보았다. 적절한 변경으로 질문을 업데이트했습니다. –