I did a memory analysis on my 200-entity creating & removing test.
Among many allocated objects, there were following:
Class | Live instances | Active size | Total Instances | Total Size | Avg age
------+----------------+-------------+-----------------+------------+--------
byte[]| 17 075 | 5 397 416 | 146 391 | 17 795 448 | 0,91
char[]| 5 848 | 522 272 | 89 025 | 13 435 464 | 1,24
I haven't profiled memory before, especially for Java, but that looks
a little worrying. There were 200 entities, and it used 17M of
byte-arrays and 13M of char arrays altogether? Sounds like a lot.
It doesn't tell which parts of program allocated those arrays
("Allocation Details" tab is nicely white and empty), but somehow it
allocates 146 391 byte arrays, each avg sized 121 bytes, and with
average age of 0.91 seconds. Not to mention the 13 million char
arrays, each with avg size of 150 bytes. What the hell is going on
here :)
Oh and I assume the profiler is *THAT* broken that it would tell wrong
results, so far only problem is that it has been confused about
generated classes and some info has been lacking, but so far I haven't
detected the profiler actually giving out wrong info.
I'm including the test as inline attachment. With one profiler
session, it said:
JUnit version 4.8.1
.18.2.2010 12:23:41
org.qi4j.entitystore.prefs.PreferencesEntityStoreMixin activate
INFO: Preferences store:/Application
24972 [main] INFO org.qi4j.index.rdf.newtests.RDFPerformanceTest -
Time to create 200 entities (ms): 2425
34253 [main] INFO org.qi4j.index.rdf.newtests.RDFPerformanceTest -
Time to complete creation uow (ms): 9281
45586 [main] INFO org.qi4j.index.rdf.newtests.RDFPerformanceTest -
Time to delete 200 entities (ms): 11332
230464 [main] INFO org.qi4j.index.rdf.newtests.RDFPerformanceTest -
time to complete deletion uow (ms): 184877
Time: 230,001
OK (1 test)
That was a particularly slow one, I think eclipse hit its max memory size.
package org.qi4j.index.rdf.newtests;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import org.qi4j.api.common.UseDefaults;
import org.qi4j.api.common.Visibility;
import org.qi4j.api.entity.EntityComposite;
import org.qi4j.api.property.Property;
import org.qi4j.api.unitofwork.UnitOfWork;
import org.qi4j.bootstrap.AssemblyException;
import org.qi4j.bootstrap.ModuleAssembly;
import org.qi4j.entitystore.prefs.PreferenceEntityStoreAssembler;
import org.qi4j.index.rdf.RdfQueryTest;
import org.qi4j.index.rdf.assembly.RdfNativeSesameStoreAssembler;
import org.qi4j.library.rdf.repository.NativeConfiguration;
import org.qi4j.test.AbstractQi4jTest;
import org.qi4j.test.EntityTestAssembler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RDFPerformanceTest extends AbstractQi4jTest
{
private static Logger _log =
LoggerFactory.getLogger(RDFPerformanceTest.class);
public interface ExampleEntity extends EntityComposite
{
@UseDefaults
Property<String> someProperty();
}
@Override
public void assemble(ModuleAssembly module) throws AssemblyException
{
PreferenceEntityStoreAssembler pAss = new PreferenceEntityStoreAssembler(
Visibility.module );
ModuleAssembly prefModule = module.layerAssembly().moduleAssembly(
"PrefModule" );
prefModule.addEntities( NativeConfiguration.class ).visibleIn(
Visibility.application );
pAss.assemble( prefModule );
module.addEntities( ExampleEntity.class );
EntityTestAssembler testAss = new EntityTestAssembler();
testAss.assemble( module );
RdfNativeSesameStoreAssembler rdfAssembler = new
RdfNativeSesameStoreAssembler();
rdfAssembler.assemble( module );
}
private List<ExampleEntity> doCreate(int howMany)
{
List<ExampleEntity> result = new ArrayList<ExampleEntity>(howMany);
for (Integer x = 0; x < howMany; ++x)
{
result.add(this.unitOfWorkFactory.currentUnitOfWork().newEntity(ExampleEntity.class));
}
return result;
}
private void doRemoveAll(List<ExampleEntity> entities)
{
for (ExampleEntity entity : entities)
{
this.unitOfWorkFactory.currentUnitOfWork().remove(this.unitOfWorkFactory.currentUnitOfWork().get(entity));
}
}
private void doRemove(int howMany)
{
Iterator<ExampleEntity> iter =
this.queryBuilderFactory.newQueryBuilder(ExampleEntity.class).newQuery(this.unitOfWorkFactory.currentUnitOfWork()).maxResults(howMany).iterator();
Integer removed = 0;
while (iter.hasNext())
{
this.unitOfWorkFactory.currentUnitOfWork().remove(iter.next());
++removed;
}
if (removed != howMany)
{
_log.warn("Removed " + removed + " entities instead of " + howMany +
".");
}
}
private void performTest(int howMany) throws Exception
{
UnitOfWork creatingUOW = this.unitOfWorkFactory.newUnitOfWork();
Long startingTime = System.currentTimeMillis();
List<ExampleEntity> entities = this.doCreate(howMany);
_log.info("Time to create " + howMany + " entities (ms): " +
(System.currentTimeMillis() - startingTime));
startingTime = System.currentTimeMillis();
creatingUOW.complete();
_log.info("Time to complete creation uow (ms): " +
(System.currentTimeMillis() - startingTime));
UnitOfWork deletingUOW = this.unitOfWorkFactory.newUnitOfWork();
//this.doRemoveAll(entities);
startingTime = System.currentTimeMillis();
this.doRemove(200);
_log.info("Time to delete " + howMany + " entities (ms): " +
(System.currentTimeMillis() - startingTime));
startingTime = System.currentTimeMillis();
deletingUOW.complete();
_log.info("time to complete deletion uow (ms): " +
(System.currentTimeMillis() - startingTime));
}
@Test
public void performanceTest200() throws Exception
{
this.performTest(200);
}
// @Test
public void performanceTest1000() throws Exception
{
this.performTest(1000);
}
// @Test
public void performanceTest5000() throws Exception
{
this.performTest(5000);
}
// @Test
public void performanceTest10000() throws Exception
{
this.performTest(10000);
}
// @Test
public void performanceTest100000() throws Exception
{
this.performTest(100000);
}
}
_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev