Terrain Quad Load Times

I run into a curious thing I don’t understand. Im loading several terrain quads in a loop. I am pre-loading the material, and textures. I have checked to make sure the textures/materials finished loading first before constructing my terrainQuads.

Yet my load times for times average as follows.

Tile #1: 120ms
Tile #2: 32ms
Tile #3: 19ms

I can’t figure out what is taking so long the first time I construct a terrain quad? The tiles have the same geometry, and all the things they rely on are preloaded before Tile #1 is instanced.

Jit compiler maybee?

I think Phoenix could be right.
About a year ago i made some test with a similar results:
It wasn’t with Terrain Quads and not even with JME but with “normal” Java. I had a method which did some calculations and this method was iterated very often. Every time i measured the time needed. The Time needed for the first run was 4 to 20 times higher than the average.

I’m not completely sure it’s the same here but it seems very likely too me.

Another thing it could be is that your times aren’t correct!?
As i did the project mentioned above i learned that exact time measuring in Java is very complex and if you do some little things wrong, the time measured can be highly falsified.

Also have you done your measuring just one time? Then it could be that it’s just a coincidence.

Does your “load time” include displaying on screen? Does your “preload” mean you’d shown them on screen before?

A texture loaded is one thing but it still has to be transferred to the GPU the first time it is used.

Really, we don’t have enough information on what exactly you are timing or how you are timing so the answers will be all over the place.

A texture loaded is one thing but it still has to be transferred to the GPU the first time it is used.

Interesting to know, but I did more checking based on this and thats not my problem.

Specificly modifinying this bit of code to produce more detailed information:

[java]

public MapTile constructTile(String tilename, float[] data)
{
   long p1 = System.currentTimeMillis();
    // Create bare tile
    MapTile myTerrain = new MapTile(
            "Test Square",msgTile.TileSize,msgTile.TileSize
            ,data);        
   System.out.print("Tile Data Loaded:"
             +(System.currentTimeMillis()-p1)+"ms\n");

[/java]

Returned these results:

Tile Data Loaded:117ms
Tile Material & LOD Added:3ms
Client Tile Render: 139ms

Tile Data Loaded:26ms
Tile Material & LOD Added:0ms
Client Tile Render: 41ms

The bulk of the lag appears to be completely in the constructor for terraquad. The time to load materials, LOD control, and add the terrainquad to the scene are 22ms or less. Which I can live with, its that 117ms to contstuct the first tile, that drops to 26ms on the second tile, less on the third tile, finally balancing out around the third tiles construction time that has me confused.

By the way, in the future, using: System.currentTimeMillis();
…to time things is like using a calendar to time a race. “Racer 1 started on January 21st and finished on January 21st! Congratulate them.”

Better to use System.nanoTime() for timing as that’s what it’s for. It probably wouldn’t change the results in this case, though.

It does seem like a Hotspot thing… the code may just have been optimized after the first loading. Or there was some caching happening internally… either way I’m not sure you can avoid it and this is the sort of thing that loading screens are meant for anyway.

No way that Hotspot inlines code that early. There must be something cached, where can I see the code of the constructor of the MapTile class? Is that a jME class?

@jmaasing said: No way that Hotspot inlines code that early. There must be something cached, where can I see the code of the constructor of the MapTile class? Is that a jME class?

It depends on what the loading is doing. If it’s iterating over a larger array (especially multidimensional) with some work in an inner loop then it is quite likely that the second call will be faster and the third slightly faster still.

In microbenchmarks I don’t usually start measuring for real until the 10th run or so but usually the times start to stabilize right after the first time if I’ve set my tests up right.

Cool, I know it inlines pretty aggressively but certainly did not expect it to JIT that early, but as you say, if there is some inner loop that does a lot of method calls the methods could probably get hot in 100 ms.
Still think it’s some caching or some I/O going on though :slight_smile:

@jmaasing said: Cool, I know it inlines pretty aggressively but certainly did not expect it to JIT that early, but as you say, if there is some inner loop that does a lot of method calls the methods could probably get hot in 100 ms. Still think it's some caching or some I/O going on though :-)

Could be… also, the array iterations themselves will be hotspotted very fast. Especially the inner loop, the index out of bounds checks can be removed after the first pass and so on… the second call to the method containing those loops would be pretty fast.

All things considered, the [y] style array access is pretty slow (comparatively) but can be optimized pretty aggressively. (Still, note that [x + y * width] is still way faster if you can convert multidimensional arrays into single dimension + math.)

@jmaasing There must be something cached, where can I see the code of the constructor of the MapTile class? Is that a jME class?

[java]
public class MapTile extends TerrainQuad
{
private Vector2f myOrigin = null;

public void setLocationByCenter(Vector2f newCenter)
{
   if((this.myOrigin != null) && (newCenter != null))
    this.setLocalTranslation(
            new Vector3f(newCenter.x+myOrigin.x,0.0f,
                        newCenter.y+newCenter.y)
            );
   else
    this.setLocalTranslation(Vector3f.ZERO);
}

public Vector2f getOrigin() { return this.myOrigin; }

public void setOrigin(Vector2f newOrigin) 
{
    this.myOrigin = newOrigin;
}

public MapTile(String name, int patchsize, int totalsize)
{
    super(name,patchsize,totalsize,null);
}

public MapTile(String name, int patchsize, int totalsize, float[] data)
{
    super(name,patchsize,totalsize,data);
}

}
[/java]