glob3mobile / g3m

The multiplatform advanced visualization framework
http://www.glob3mobile.com/
Other
117 stars 56 forks source link

reduce number of memory allocations on Android #73

Closed akosmaroy closed 9 years ago

akosmaroy commented 10 years ago

I'd suggest adopting an approach to reduce a large number of recurring small object allocations, because on Android this is a considerable performance bottleneck. these small objects get discarded, and later the garbage collector will have to get rid of them, causing a GC bottleneck that is undesirable, and also 'hogs' the application (by having a lock on memory allocation while doing GC)

my suggestion would be to adopt coding patterns which don't do micro-allocations by returning newly created objects - instead, they use 'out parameters' that are function parameters, and write the results into these objects. this way, the objects need to be allocated only once, and then they are naturally re-used.

in general, functions that are read-only (like rendering of checking for read-only properties like isVisible()) should not do any allocations

for details, please see a memory allocation list for our application using G3M. this is an output of the DDMS memory allocation tracker from within eclipse. as the data can't be exported, here is some screenshots instead:

alloc1

now what is visible is that most of the allocation is done in an otherwise supposedly read-only function in Tile.isVisible():

alloc2 alloc3

and some is done in another supposedly read-only function, in Mesh.render():

alloc4

I think the below case demonstrates the pattern behind the problem. all these Vector3D allocations are done in a single function:

alloc5

the function being:

  public final Vector3D toCartesian(Angle latitude, Angle longitude, double height)
  {
    final Vector3D n = geodeticSurfaceNormal(latitude, longitude);

    final Vector3D k = _ellipsoid.getRadiiSquared().times(n);
    final double gamma = IMathUtils.instance().sqrt((k._x * n._x) + (k._y * n._y) + (k._z * n._z));

    final Vector3D rSurface = k.div(gamma);
    return rSurface.add(n.times(height));
  }

for the stack grace / call graph, see the image above.

this single call is responsible for 5 allocations of a Vector3D object, all of which are thrown away immediately.

but this is just an example, the Matrix4D operations on the top of the first screenshots provided above have the same allocation issue

akosmaroy commented 10 years ago

please advise on how to set up our separate branch to try to re-write some of the code so that it doesn't do these micro-allocations. by setting up I'd need info on how to have the automated code-generation process work on that branch and generate the Java code based on the C++ code

alternatively we can try to re-write stuff in Java, but that's re-writing generated code, which doesn't sound like a good idea

DiegoGomezDeck commented 10 years ago

Hello Akos,

I think I already sent you the instructions to run the conversor. We have a jenkins running on one server of us, where you can fire the conversion process on any branch… when this process ends, the conversor-results are pushed to the same branch.

In any case, I recommend you to wait for a couple of days as the changes I have on 'rasterizer-refactor’ branch are big and I expect conflicts there.

— Diego

On May 4, 2014, at 6:52 AM, Ákos Maróy notifications@github.com wrote:

please advise on how to set up our separate branch to try to re-write some of the code so that it doesn't do these micro-allocations. by setting up I'd need info on how to have the automated code-generation process work on that branch and generate the Java code based on the C++ code

alternatively we can try to re-write stuff in Java, but that's re-writing generated code, which doesn't sound like a good idea

— Reply to this email directly or view it on GitHub.