package org.rapidbeans.datasource; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import junit.framework.TestCase; import org.rapidbeans.core.basic.RapidBean; import org.rapidbeans.core.exception.RapidBeansRuntimeException; import org.rapidbeans.core.type.TypePropertyCollection; import org.rapidbeans.test.codegen.Address; import org.rapidbeans.test.codegen.AddressBook; import org.rapidbeans.test.codegen.Person; /** * Test heap space needs and garbage collection for a bean array. * * @author Martin Bluemel */ public final class BBDocumentMemoryPerfTest extends TestCase { /** * set the default collection class to array list to achive the desired * perfomance. */ public void setUp() { TypePropertyCollection.setDefaultCollectionClass(ArrayList.class); } /** * reset the default default collection class. */ public void tearDown() { try { return; } finally { TypePropertyCollection.setDefaultCollectionClass(TypePropertyCollection.DEFAULT_COLLECTION_CLASS_DEFAULT); } } /** * this test prooves that deleting a bean out of a document releases the * bean for garbage collection. * * @throws InterruptedException * because of Thread.sleep. */ public void testDeleteBeans() throws InterruptedException { final int count = 100000; RapidBean[] array2 = new RapidBean[count / 2]; for (int i = 0; i < count / 2; i++) { array2[i] = new Address(); } // add the first set of beans to a document System.out.println("[BBDocumentMemoryPerfTest]" + " adding the first set of " + count + " beans to a document..."); Thread.sleep(100); AddressBook root = new AddressBook(); Document doc = new Document("test", root); Person[] array = new Person[count]; Person bean; int p = 0; int pCurrent; Runtime.getRuntime().gc(); Thread.sleep(100); final long freeBytesBefore = Runtime.getRuntime().freeMemory(); System.out.println("[BBDocumentMemoryPerfTest]" + " free Bytes: " + freeBytesBefore); for (int i = 0; i < count; i++) { bean = BBDocumentIORuntimePerfTest.generatePerson(); root.addPerson(bean); assertSame(bean, doc.findBean(bean.getType().getName(), bean.getIdString())); // store the bean for deletion array[i] = bean; pCurrent = (int) ((((double) i / count)) * 100); if (pCurrent > (p + 1)) { System.out.print("."); Thread.sleep(100); p = pCurrent; } } System.out.println(); Runtime.getRuntime().gc(); Thread.sleep(100); final long consumedBytes = freeBytesBefore - Runtime.getRuntime().freeMemory(); System.out.println("[BBDocumentMemoryPerfTest]" + " free Bytes: " + Runtime.getRuntime().freeMemory()); System.out.println("[BBDocumentMemoryPerfTest]" + " consumed " + consumedBytes + " Bytes totally."); final long bytesPerBean = consumedBytes / count; System.out.println("[BBDocumentMemoryPerfTest]" + " consumed " + bytesPerBean + " Bytes per bean."); // add the second set of beans to a document // and expect an OutOfMemoryProblem System.out.println("[BBDocumentMemoryPerfTest]" + " adding a 2nd set of " + count + " beans to the document without deleting a bean..."); Thread.sleep(100); p = 0; try { for (int i = 0; i < count; i++) { bean = BBDocumentIORuntimePerfTest.generatePerson(); root.addPerson(bean); assertSame(bean, doc.findBean(bean.getType().getName(), bean.getIdString())); pCurrent = (int) ((((double) i / count)) * 100); if (pCurrent > (p + 1)) { System.out.print("."); Thread.sleep(100); p = pCurrent; } } fail("expected RapidBeansRuntimeException or OutOfMemoryError"); } catch (RapidBeansRuntimeException e) { final Throwable e1 = e.getCause(); assertTrue("caught BBRuntimeException with cause different from InvocationTargetException" + e1.getClass().getName() + ": " + e1.getMessage(), e1 instanceof InvocationTargetException); final Throwable e2 = e1.getCause(); assertTrue("caught InvocationTargetException with nested exception different from OutOfMemoryError: " + e2.getClass().getName() + ": " + e2.getMessage(), e2 instanceof OutOfMemoryError); System.out.println("[BBDocumentMemoryPerfTest] got an InvocationTargetException" + " caused by an OutOfMemoryError as expected"); } catch (OutOfMemoryError e) { System.out.println(); System.out.println("[BBDocumentMemoryPerfTest] got an OutOfMemoryError as expected"); } // delete count beans and try again array2 = null; System.out.println("[BBDocumentMemoryPerfTest] deleting the first set of beans from the document..."); Thread.sleep(100); p = 0; for (int i = 0; i < count; i++) { bean = array[i]; bean.delete(); array[i] = null; pCurrent = (int) ((((double) i / count)) * 100); if (pCurrent > (p + 1)) { System.out.print("."); Thread.sleep(100); p = pCurrent; } } System.out.println(); // add a third set of beans to a document System.out.println("[BBDocumentMemoryPerfTest]" + " adding again the 2nd set of " + count + " beans to the document..."); Thread.sleep(100); p = 0; for (int i = 0; i < count; i++) { bean = BBDocumentIORuntimePerfTest.generatePerson(); root.addPerson(bean); assertSame(bean, doc.findBean(bean.getType().getName(), bean.getIdString())); pCurrent = (int) ((((double) i / count)) * 100); if (pCurrent > (p + 1)) { System.out.print("."); Thread.sleep(100); p = pCurrent; } } System.out.println(); } }