views:

181

answers:

4

It is a Java issue in general, though in this particular case I am using Vertex Arrays in Android for OpenGL. To use this basic GL system, you must use Java's Buffer system in native allocation mode. This is very slow on Java. And roughly 40-50% of my entire application's time is spent inside of buffer.put().

Is there any way to speed this up while staying in Java (ie, don't use the native sdk)?

A: 

This is not really an answer, but be sure to test on 2.2 with the JIT. I know that's not what you're looking for, but perhaps (if the slowness is in the java and not the native allocation) the compilation speedup would help fix this. Again, I know it's not an answer but it would at least be interesting to try.

Hamy
2.2 is basically fine anyways as all phones that run 2.2 (N1) are very fast already. However I'm also targeting 1.6 on the Ht-03a which is the slowest beast of an android phone out there :)
Moncader
A: 

The only thing you can do really is to batch your jobs and hope the implementation in the phone is decent, since the penalty comes from locking and unlocking. If you batch your calls the driver should lock and unlock once. If you do it "spontaneously" you will lock and unlock all the time, which will give you a hefty performance hit. If the driver isn't clever enough to only map the buffers into ram once instead of for every call your best bet is to simply minimize the number of puts.

Tobias
What would a driver have to do with native buffers in Java? The slow part is not uploading the buffers in to OpenGL memory, its the actual Java buffers themselves.
Moncader
+1  A: 

Avoid allocations in general. Use a pool of buffers and juggle them around as needed. You can have a few standard sizes and waste a few bytes at the end in exchange for performance. Also, when using OpenGL you typically don't need to rewrite your buffers every frame (unless you do extensive skinning or animation?). Normally, you have your pre-baked arrays, transform objects using matrices, and that's it.

EboMike
The allocations aren't the problem. I only allocate once on program startup. It's the changing of the allocated buffers (with the put() method) that is slow.As for rewriting the buffers, I found that in Java on Android having a few buffers that change values is better than allocating hundreds of separate buffers (due to memory consumption). I'm using a couple buffers and changing the values in them as needed (sadly every frame).
Moncader
This wasn't a full answer, but it provides the best advice for trying to avoid this problem in the first place. So I've given you the bounty and answer (As it is useful information anyways)
Moncader
Thank you! My only other suggestion, in true "duh" style, is to try to avoid changing the values every frame? What is changing? Are your meshes deforming? Can you separate between changing buffers and static buffers and keep all changing data within the same area of those buffers? (=all at the beginning, for example)
EboMike
I'm using the same buffer to display multiple items and just use GL transformations to move the same item around the screen. In the case of only moving, I do not rewrite the buffers, just translate them in gl world. However, each item is no guarunteed to have the same size (or even ratio) as the next, in which case, if and only if the item size is different from the previous one, I must rewrite the buffer.
Moncader
If you just translate them, don't modify the buffers - just use a matrix to transform them. (It sounds like you're already do that?) What other modifications do you have that require you to modify the buffers?
EboMike
+1  A: 

I've encountered a similar problem when integrating Java and JOGL - my solution was to manage the buffer resources in C, and use JNI to pass the pointer to the buffer to Java using the method

jobject NewDirectByteBuffer(JNIEnv * env, void * address, jlong capacity); 

found in jni.h. When you need to update the offset into the buffer, use reflection to manually modify the "address" field found in java.nio.Buffer. If adding more elements would cause you to exceed the capacity of the buffer in C, use an array list in C and have the direct buffer point to the array backing for the list.

Very interesting solution. However I'd like to stay away from any native coding. I'll be keeping this in mind for later though.
Moncader