Re: [sdljava-users] Usage example for glGetDoublev
Status: Beta
Brought to you by:
ivan_ganza
From: Robert S. <the...@gm...> - 2005-09-13 22:26:16
|
Hi Gregor, this is an impressive nice benchmark. Look what our free VMs can achieve: rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ LD_LIBRARY_PATH=. gij Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 2705 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 2242 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 4329 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 1047 (This is GCJ 4.0 somewhat.) rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ LD_LIBRARY_PATH=. jamvm Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 1825 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 1443 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 7916 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 278 rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ (Both are interpreted only. JamVM has a handcrafted JNI implementation that really outperforms the JDK) As a comparison my JDK 1.5.0 results: LD_LIBRARY_PATH=. /opt/sun-jdk-1.5.0/bin/java Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 484 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 386 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 15891 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 287 However your point seems to be valid. Frequent allocations of direct buffers kill performance. In my opinion this is very sad for Java because it means if (amountOfData < someMagicValue) { GL.glVertex3fv(new int[] { foo, baz, bar, ... }); } else { IntBuffer b = BufferUtils.createBuffer(...); b.put(...); GL.glVertex3fv(b); } Gregor would you mind giving your benchmark a GPL or GPL-compatible license so I may be allowed to put it into mauve (the free test suite)? I am sure Robert Lougher (JamVM) and the GCJ team is pretty interested about these results. Oh yes and you're right. For maximum control over performance GLJava should provide OpenGL's v-functions with Java arrays exactly in the way you did it in the benchmark. And then the Javadoc should mention when to use which version ... cu Robert Gregor Mückl wrote: > Hi! > > I've finally tried to benchmark java arrays and direct buffers in small > buffers of the size that would typically appear in OpenGL apps. The results > of the runs on my computer are: > > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 1033 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 817 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 32803 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 560 > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 1034 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 776 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 34588 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 591 > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 984 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 768 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 35151 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 615 > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 1093 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 847 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 35321 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 623 > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 730 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 575 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 22455 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 438 > > The source code for the benchmark is included. This clearly shows that direct > buffers are really only viable if you can avoid their allocation. But now the > problem is that caching ByteBuffers would add considerable overhead to the > results of the last measurements in both sourcecode complexity and runtime. > Furthermore, caching unused data structures in Java is especially bad design > and any suggestion to that end can easily be seen as a sign of bad design > elsewhere. And in reality it may really not be feasible. I'm writing a 3d > modelling tool which cannot apply proper rendering optimizations because the > geometry may essentially be anything and change at any time to anything else. > So I have to use thousands of calls to glVertex3d(v) and similar. > > Compared to direct buffers even the reallocated arrays don't have so much > added overhead. So I strongly suggest that you implement arrays at least as > an alternative interface. It's easy to overload functions in Java, so this is > not a problem. > > The source code to the benchmark is appended. > > Regards, > Gregor > > On Tuesday 13 September 2005 04:17, Ivan Z. Ganza wrote: > >>Thanks for the very detailed information :-) >> >>The helpful class is sdljava.util.BufferUtil...which Robert kindly >>coded. Interesting to have a look at the code inside... >> >>Please let us know if your able to make it work Gregor. >> >>-Ivan/ >> >>Robert Schuster wrote: >> >>>Hi, >>>I just want to jump into the discussion because I was one of the persons >>>who suggested Ivan to use NIO buffers instead of Java arrays (and I have >>>some small background about the topic from JNI and GNU Classpath coding). >>> >>> >>>>The biggest buffer I use that way is there to store a matrix of >>>>4x4 doubles, that is, 128 bytes. >>> >>>Perfect. This is really the point where you can use NIO buffers. It may be >>>look odd to you but a regular Java array is more troublesome than a NIO >>>buffer. The buffer is an object denoting a certain memory region. >>>Therefore you can think of it as a thin wrapper around a normal C array >>>(or memory region that allocated with malloc/calloc). >>> >>>A Java array is something that lifes inside the JVM and can be implemented >>>very differently. NIO buffers and Java arrays have very similar JNI >>>functions to interact with them. Both have a function which returns a >>>pointer so that you can modify the data in C-style. However the array >>>access function explicitly states that you *may* receive the pointer to a >>>copy of the original data (remember that Java arrays life in the JVMs >>>heap and may be moved around because of garbage collection and memory >>>compaction). This won't happen with NIO buffers. >>> >>>If you have a feeling that frequent bytebuffer instantiations would harm >>>the performance of your application then please have a look whether you >>>may not solve this problem in a different way (e.g. pooling buffers or >>>the like). >>> >>> >>>>Using byte buffers may be a valid approach when working on large, uniform >>>>amounts of data like framebuffers. But that is not the case with geometry >>>>data for OpenGL. Using vertex arrays is almost out of question for me >>>>since the geometry data I have is very dynamic in every way. >>> >>>Definitely not. NIO buffers can be used wherever interaction with native >>>machinery is involved. I once wrote a jinput plugin which uses the Linux >>>kernel's input system to access mouse/keyboard/joypad etc (You can find >>>the sources in the respective forums at javagaming.org). It makes heavy >>>use of NIO buffers even for such small amounts of data (key/button/axes >>>states) and I think it is a big win that the system's kernel can write >>>into the memory which it shares with my Java application. >>> >>> >>>>Well, this is not trying to be a rant. I'm just not yet convinced that >>>>this is the right approach. It looks like far too much overhead to me, >>>>making all the OpenGL functions taking (small) arrays practically >>>>useless. >>> >>>Well, in which way could they be implemented otherwise? At one point you >>>will forced to create a buffer in memory (probably C). If you hand over >>>the data in Java arrays and copy it over into a malloc'ed memory region >>>then this would hit performance seriously (You need one copy operation >>>and one time malloc/free in GLJava's code.) With NIO buffers the JNI >>>implementation would simply return the buffer's pointer and call the >>>OpenGL function. The handling of the buffer (recreate it every time or do >>>some pooling) is up to you - the application programmer. >>> >>> >>>>Maybe some >>>>benchmarking is in order to get some definitive answers, but I don't have >>>>enough time for that. >>> >>>Well I try to prove it with a bit of pseudo code. (I use pseudo code >>>because I dont know the JNI function names by heart. They are very >>>tedious ...) >>> >>> >>>1. With Java arrays >>>GL.java >>> >>>public class GL { >>> public native setSomethingv(int[] foo); >>>} >>> >>>net_sf_GL.c: >>> >>>setSomethingv(jvm, jobject java_array){ >>> >>> jint* thevalues = JVM_get_pointer_to_java_array(java_array); // may >>>copy >>> >>> int size = JVM_get_size_of_java_array(java_array); >>> >>> int* buffer = malloc(sizeof(int) * size); >>> >>> memcopy(thevalues -> buffer, size * sizeof(int)); >>> >>> GLsetSomething(buffer); >>> >>> JVM_release_access_to_java_array(java_array); >>>} >>> >>>2. With NIO buffers >>> >>>public class GL { >>> public native setSomethingv(IntBuffer foo); >>>} >>>net_sf_GL.c: >>> >>>setSomethingv(jvm, jobject nio_buffer){ >>> >>> jint* thevalues = JVM_get_pointer_of_nio_buffer(nio_buffer); >>> >>> GLsetSomething(thevalues); >>> >>> JVM_release_access_to_java_array(java_array); >>>} >>> >>>(I am broadly ignoring any type conversion oddities here.) >>> >>>Btw: There is a utility class in GLJava that creates direct Integer, Long, >>>Short, Double and Float buffers in one method call (In fact every newer >>>OpenGL binding* has these methods ...) >>> >>>cu >>>Robert >>> >>>* JOGL, LwJGL >>> >>> >>>------------------------------------------------------- >>>SF.Net email is Sponsored by the Better Software Conference & EXPO >>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle >>>Practices Agile & Plan-Driven Development * Managing Projects & Teams * >>>Testing & QA Security * Process Improvement & Measurement * >>>http://www.sqe.com/bsce5sf >>>_______________________________________________ >>>sdljava-users mailing list >>>sdl...@li... >>>https://lists.sourceforge.net/lists/listinfo/sdljava-users >> >>------------------------------------------------------- >>SF.Net email is Sponsored by the Better Software Conference & EXPO >>September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices >>Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA >>Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf >>_______________________________________________ >>sdljava-users mailing list >>sdl...@li... >>https://lists.sourceforge.net/lists/listinfo/sdljava-users |