Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (512)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (576)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2 3
  ignore  |  Print  
  Bound's checks and struct's  (Read 14104 times)
0 Members and 1 Guest are viewing this topic.
Offline Mark Thornton

Senior Duke





« Posted 2005-10-14 18:49:40 »

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
class MyStruct {
   private ByteBuffer buffer;

   public void setBuffer(ByteBuffer b) {
      ByteBuffer buf = b.duplicate();  // isolate from changes elsewhere
      buf.clear();
      if (buf.limit() < 32) throw new Exception("too small");
      buf.order(ByteOrder.native());
      buffer = buf;
   }

   public int getX() {return buffer.getInt(0);}
   public int getY() {return buffer.getInt(4);}
   // etc
}


All we need is a compiler clever enough to notice that the bounds checks in buffer.getInt(0) can be eliminated because the buffer limits are checked in the setBuffer method. Furthermore it ought to be possible to deduce that the buffer is in native order. On x86 this ought to be sufficient to allow replacement of the getX() method by a trivial memory load. Some other machines will require further tests for alignment.

Offline Linuxhippy

Senior Duke


Medals: 1


Java games rock!


« Reply #1 - Posted 2005-10-14 21:24:16 »

Quote
All we need is a compiler clever enough to notice that the bounds checks in buffer.getInt(0) can be eliminated because the buffer limits are checked in the setBuffer method. Furthermore it ought to be possible to deduce that the buffer is in native order. On x86 this ought to be sufficient to allow replacement of the getX() method by a trivial memory load. Some other machines will require further tests for alignment.

I am quite sure it isn't since that would also include flow-analysis and wouln't be that easy to do,
I am not 100% sure and do not want to tell you anything wrong, but as far as I know no runtime which provides bounds-checks is able to handle this sort of optimizations (no JVM and no .NET runtime).

lg Clemens
Offline Mark Thornton

Senior Duke





« Reply #2 - Posted 2005-10-15 10:18:07 »

It doesn't seem much more complex than some of the analysis that is already being done or considered.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline princec

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #3 - Posted 2005-10-15 10:51:05 »

I bet it is. Besides, it's not as nice as solution as mapped objects which are dead easy to implement Wink

Cas Smiley

Offline Linuxhippy

Senior Duke


Medals: 1


Java games rock!


« Reply #4 - Posted 2005-10-15 12:50:59 »

Well, if there is doubt why not benchmark it, if its not that important since there are no perforance problems anyway ... why worry - in this case its just wasted time.

btw. I bet hotspot isnt able to optimize the checks away - sure it is if you use it in a loop since the method will become inlined and therefore its not much more than normal array-accessing code in a loop - but for random access I bet the bounds checks are not removes.

lg Clemens
Offline Mark Thornton

Senior Duke





« Reply #5 - Posted 2005-10-15 14:03:48 »

I don't expect the current hotspot compiler to be able to optimise this usage, but it is an alternative that may be worth considering as a solution to Cas's needs. It also may improve performance for other cases as well.
Offline abies

Senior Duke





« Reply #6 - Posted 2005-10-15 17:52:54 »

There is still a question of ByteBuffer being direct or heap-based. There is no way it can be guaranteed with this code, only chance would be to see execution profile - but still, there would need to be a trap for non-common case in addition to simple memory load.

Artur Biesiadowski
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #7 - Posted 2005-10-18 15:43:44 »

If you view your ByteBuffer as an IntBuffer and load the ints through the IntBuffer then the code will be optimized as you expect. JOGL uses this technique (multiple views of the same ByteBuffer depending on the type of C field being loaded) in its internal StructAccessor class for accessing C structs.
Offline princec

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #8 - Posted 2005-10-18 18:05:36 »

Aye, I use this very technique for accessing complex vertex data in my bumpmapped background stuff in 'Flux etc. but the thing is, it's such horrendous syntax and requires an absolute ton of bounds checks which are basically impossible to optimise away. And that was when I alighted upon the idea of MappedObjects ("Structs").

Cas Smiley

Offline Ken Russell

JGO Coder




Java games rock!


« Reply #9 - Posted 2005-10-19 16:25:56 »

As long as the underlying ByteBuffer is appropriately sized there should be no need for additional explicit bounds checks. The only trick is automatically figuring out the offsets for the various fields and generating accessor and setter methods. The GlueGen tool used by JOGL does this automatically for all of the C structs it encounters while parsing the input header files. However this is not necessarily a good solution for all Java programmers given that it requires learning a new tool. Peter Ahe recently discussed 4820062 with me and suggested that it could be implemented in similar fashion via annotation processing with no JVM or language changes, which sounds like a good idea to me.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline princec

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #10 - Posted 2005-10-19 19:01:03 »

Annotations will not be sufficient nor necssary; you will need to extend an abstract JDK MappedObject class and there will need to be a bit of jiggery pokery in the system classloader. Would be good to talk to you both in more detail about my designs...?

Cas Smiley

Offline Ken Russell

JGO Coder




Java games rock!


« Reply #11 - Posted 2005-10-19 20:44:19 »

I disagree. Minor syntactic details aside, it is already possible to generate the appropriate Java code to access C structs and arrays of C structs via NIO. Again, JOGL's GlueGen tool does this. Have you looked at the generated code it produces for the JAWT, XVisualInfo and other C data types? Aside from having to maintain multiple views of the underlying ByteBuffer (which is an implementation detail) the generated machine code is exactly as desired.

Similar Java code could be autogenerated using the annotation processing tool. I don't know the syntax exactly but I recall Peter mentioning something like this:
1  
2  
3  
4  
5  
  public @Struct class MyCStruct {
    public @int32_t int firstIntField;
    public @float secondFloatField;
    ...
  }

which when processed via APT would produce something like
1  
2  
3  
4  
5  
6  
7  
  public class MyCStruct {
    public MyCStruct(ByteBuffer buf);
    public int firstIntField();
    public void firstIntField(int val);
    public float secondFloatField();
    public void secondFloatField(float val);
  }

which is similar to what GlueGen produces today. APT could similarly generate an associated class representing an array of this C data type. Again, all of this is possible without modifying the language, JVM or libraries.

If you feel this is somehow insufficient then please write up your proposal on a web page somewhere and send around a link.
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #12 - Posted 2005-10-19 23:31:22 »

As long as the underlying ByteBuffer is appropriately sized there should be no need for additional explicit bounds checks.

Do you mean that each setXXX or getXXX method would not do any bounds checks?  I believe the goal with the structs proposal is that you essentially end up with something like a "StructBuffer" analogous to an IntBuffer or FloatBuffer, where the index refers to a particular 'struct' in the buffer and so once you have a struct you know that all field access' are within bounds.

I'll assume that any overhead of using getter/setter methods to peek into the underlying ByteBuffer will be optimized away by HotSpot.

Offline Ken Russell

JGO Coder




Java games rock!


« Reply #13 - Posted 2005-10-20 01:34:54 »

As long as the underlying ByteBuffer is appropriately sized there should be no need for additional explicit bounds checks.

Do you mean that each setXXX or getXXX method would not do any bounds checks?  I believe the goal with the structs proposal is that you essentially end up with something like a "StructBuffer" analogous to an IntBuffer or FloatBuffer, where the index refers to a particular 'struct' in the buffer and so once you have a struct you know that all field access' are within bounds.

As long as the underlying ByteBuffer is appropriately sized then yes, there is no need for additional bounds checks.

Quote
I'll assume that any overhead of using getter/setter methods to peek into the underlying ByteBuffer will be optimized away by HotSpot.

As long as you maintain multiple views of the underlying ByteBuffer depending on the type of field you're fetching out of the struct then yes, HotSpot generates optimal machine code. The getInt(), etc. methods on a ByteBuffer are typically not optimized (and usually can not be due to alignment issues on non-x86 platforms). I would strongly encourage you to check out the JSR-231 branch of the JOGL sources (which will soon be promoted to the main trunk) and look at the StructAccessor class in com.sun.gluegen.runtime. if you build the source tree you can see how the various autogenerated Java-side struct wrappers like JAWT_DrawingSurfaceInfo use that class.
Offline swpalmer

JGO Coder


Exp: 12 years


Where's the Kaboom?


« Reply #14 - Posted 2005-10-20 04:13:06 »

[
Quote
I'll assume that any overhead of using getter/setter methods to peek into the underlying ByteBuffer will be optimized away by HotSpot.

As long as you maintain multiple views of the underlying ByteBuffer depending on the type of field you're fetching out of the struct then yes, HotSpot generates optimal machine code. The getInt(), etc. methods on a ByteBuffer are typically not optimized (and usually can not be due to alignment issues on non-x86 platforms).

Well the multiple view thing seems like it could get a bit awkward, if you were to try to code this by hand.  But overall this sounds quite cool.  I will have to check out that gluegen stuff you speak of.  Other than looking at the JOGL source, where would I go to learn about those tools?

Offline Ken Russell

JGO Coder




Java games rock!


« Reply #15 - Posted 2005-10-20 04:57:20 »

There isn't a lot of documentation for GlueGen at the moment. I believe some is embodied in comments in the source code and usage statements but the configuration files used to drive the glue code generation are completely undocumented right now. Documenting it is a medium-priority task but completing JSR-231 takes precedence.
Offline princec

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #16 - Posted 2005-10-20 18:40:38 »

Your proposal does not quite meet the requirements I have.

The precise requirement I have is to map primitive fields, in-order, directly, into a ByteBuffer. No getters or setters. And no bounds checks in the get or set methods, which you will have to have with any generated code, as Hotspot will not be able to determine whether they are within the boundary of the ByteBuffer. And no source code generation.

A MappedObject must have a final ByteBuffer in which it lives, and a current position within that bytebuffer. The ability of the JVM to read and/or write fields efficiently will depend on the byte alignment of the underlying bytebuffer and struct position and field position.

Because MappedObject.setPosition() sets the position and relative position of all the fields simultaneously, this is the only time that a bounds check must be performed on the bytebuffer, to ensure that the first and last fields are within the limits specified by the buffer.

Object reference fields are simply ignored for all purposes.

MappedObject is an abstract class that should be placed in java.nio.

That's all it needs.

Cas Smiley

Offline Mark Thornton

Senior Duke





« Reply #17 - Posted 2005-10-20 20:12:17 »

And no bounds checks in the get or set methods, which you will have to have with any generated code, as Hotspot will not be able to determine whether they are within the boundary of the ByteBuffer.
Ken seems to be implying that HotSpot can already eliminate the bounds checks and thus achieve the performance part of your requirements.
Offline abies

Senior Duke





« Reply #18 - Posted 2005-10-20 20:51:42 »

Code is probably better than words.

What can be done with a bit of hackery

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;

import sun.misc.Unsafe;

public class MappedObject {

  static Unsafe unsafe;
  static Field addressHack;
  static {
    try {
      ByteBuffer bb = ByteBuffer.allocateDirect(1);
      Field unsafeHack = bb.getClass().getDeclaredField("unsafe");
      unsafeHack.setAccessible(true);
      unsafe = (Unsafe) unsafeHack.get(bb);

      addressHack = Buffer.class.getDeclaredField("address");
      addressHack.setAccessible(true);
    } catch (Exception exc) {
      exc.printStackTrace();
    }

  }

  private long base;

  public final void attach(ByteBuffer bb, int offset) {
    try {
      base = addressHack.getLong(bb) + offset;
    } catch (Exception exc) {
      exc.printStackTrace();
      throw new InternalError();
    }
  }

  public int getY() {
    return unsafe.getInt(base + 8);
  }

  public void setY(int y) {
    unsafe.putInt(base + 8, y);
  }

  public int getX() {
    return unsafe.getInt(base + 16);
  }

  public void setX(int x) {
    unsafe.putInt(base + 16, x);
  }

  public static void main(String[] argv) {

    MappedObject mo = new MappedObject();
    ByteBuffer bb = ByteBuffer.allocateDirect(1000);
    mo.attach(bb, 128);

    mo.setY(1);
    for (int i = 0; i < 500; i++) {
      test(mo);
    }
    System.out.println(mo.getX());
  }

  private static void test(MappedObject mo) {
    for (int i = 0; i < 1000000; i++) {
      mo.setX(mo.getY() + mo.getX());
    }
  }

}


And this is how inner stride of loop inside test method looks like

1  
2  
3  
4  
5  
6  
7  
040   B4: #   B4 B5 <- B3 B4    Loop: B4-B4 inner stride: not constant  Freq: 7.51066
040      MOV    EDI,[EAX + #8]
043      ADD    ECX,EDI
045      MOV    [EAX + #16],ECX
048      INC    EBX
049      CMP    EBX,#1000000
04f      Jlt,s  B4  P=1.000000 C=7.509333



When playing with this code, I have seen once that hotspot unrolled this inner loop by 4, but I was not able to reproduce it, for whatever reasons.

I think it clearly shows, that it is perfectly possible to write well performing struct class using today jvm. Only problem is that you have to use getter/setter instead of direct field access - which can be a clarity issue, but doesn't affect the performance in slightest way.

MappedObject  class would have to be made abstract, with subclasses for specific structures. It also requires full rights in jvm and performs no checks currently - but a adding check in attach would be exactly what you mentioned and should not affect the performance.

Artur Biesiadowski
Offline princec

JGO Kernel


Medals: 404
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #19 - Posted 2005-10-20 23:30:40 »

I would dearly like to be able to remove get/set methods for the purposes of clarity. Consider writing a dot product for a mapped vector3f class - yuk. Besides not all of the fields should necessarily be exposed! This is OOP remember. get/set is a crap paradigm.

Cas Smiley

Offline abies

Senior Duke





« Reply #20 - Posted 2005-10-21 09:49:03 »

Then let's vote for C#-like properties, which gives you nice short syntax and total lack of knowledge about side effects of simple assignments.

Anyway, even for that there is a 'soft' solution - bytecode translation on runtime (which is currently nicely exposed in core java API). Yes, it is a bit of hack, but benefit is that it will not extend a language in any way for people who don't want it. For you, it would be just putting one call at start of application to apply the bytecode filter, plus importing one library (this library being very dependent on JDK version unfortunately, not to mention vendor even).

So, below example would be something like

1  
2  
3  
4  
public final class XYWithSomeGaps extends MappedStructure {
  @Offset(8) public int x;
  @Offset(16) public int y;
}


MappedStructure would expose only attach method. You would directly access x,y fields on XYWithSomeGaps. Runtime bytecode weaver would convert XYWithSomeGaps to contain getters/setters and all needed magic for conversions (if fields are not defined to be in native endianess for example), plus would convert every access to it to getX/getY/etc. Hotspot would then convert these accessors back to direct memory references Smiley


Artur Biesiadowski
Offline Linuxhippy

Senior Duke


Medals: 1


Java games rock!


« Reply #21 - Posted 2005-10-21 10:10:09 »

Well, great idea.

Lets make Java to what C++ was - a really fat and bloated language, hard to learn really hard to build compilers for.
Java really gets fat - boxing is nice and generics are too (from my point of view it was a fault to include this later on) but isnt that enough.
Whats about direct, unchecked memory access. Would for sure boost performance, but to what price??

hmm, lg Clemens
Offline Mark Thornton

Senior Duke





« Reply #22 - Posted 2005-10-21 10:17:12 »

Can the same performance be achieved without the Sun specific unsafe hacks?
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #23 - Posted 2005-10-21 10:18:48 »

Mapped Object wouldn't be adding bloat, really. And it's not unsafe at all.

Mapped Objects wouldn't be allocated on the heap, but in a native (properly ordered) ByteBuffer.

That's all there is to it.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline abies

Senior Duke





« Reply #24 - Posted 2005-10-21 10:33:55 »

Lets make Java to what C++ was - a really fat and bloated language, hard to learn really hard to build compilers for.

Nothing we can come up with will be uglier, more complicated for compilers, less clear than generics as they are currently.

Quote
Whats about direct, unchecked memory access. Would for sure boost performance, but to what price??

If you need it, you need it. You need to it to the point of scrapping all the java just because lack of it.

I partially agree with you - it is probably too specific to be incorporated in mainstream java. I think that some combination of annotations, Unsafe hackery and bytecode weaver is just enough to get everything Cas wants.

Artur Biesiadowski
Offline abies

Senior Duke





« Reply #25 - Posted 2005-10-21 10:37:00 »

Can the same performance be achieved without the Sun specific unsafe hacks?

I have tried to do similar class on ByteBuffer (just replacing every get/set method with access to buffer)... Enought to say that inner loop had like 100 cpu instructions instead of 6 including 4-5 branches instead one at end. That was after making byte buffer native order, before it was even worse (hotspot was actually calling some methods inside the loop).

Maybe there is some trick to get this improved - I cannot find it at the moment.

Artur Biesiadowski
Offline Mark Thornton

Senior Duke





« Reply #26 - Posted 2005-10-21 10:57:53 »

I have tried to do similar class on ByteBuffer (just replacing every get/set method with access to buffer)...
Have you tried an IntBuffer view on the ByteBuffer? Apparently this is necessary to get any optimisation.
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #27 - Posted 2005-10-21 11:24:47 »

I've benchmarked these two classes:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
   private static class ClazzA
   {
      public int a, b, c;
      public float x, y, z;
   }

   private static class ClazzB
   {
      private final static int ALIGN = 4;
      private final static int SIZEOF = (3 + 3) * ALIGN;
      private final static ByteBuffer bb = BufferUtils.createByteBuffer(SIZEOF * 64);
      private final static IntBuffer ib = bb.asIntBuffer();
      private final static FloatBuffer fb = bb.asFloatBuffer();
      private static int nextOffset = 0;

      private final int off;



      public ClazzB()
      {
         off = nextOffset;

         nextOffset += SIZEOF / ALIGN;
      }



      public final void a(int a) { ib.put(off+0, a); }
      public final void b(int b) { ib.put(off+1, b); }
      public final void c(int c) { ib.put(off+2, c); }
      public final void x(float x) { fb.put(off+3, x); }
      public final void y(float y) { fb.put(off+4, y); }
      public final void z(float z) { fb.put(off+5, z); }
      public final int a() { return ib.get(off+0); }
      public final int b() { return ib.get(off+1); }
      public final int c() { return ib.get(off+2); }
      public final float x() { return fb.get(off+3); }
      public final float y() { return fb.get(off+4); }
      public final float z() { return fb.get(off+5); }
   }




The benchmark did this calculation on the instances:

1  
2  
3  
4  
5  
6  
7  
8  
9  
                  a.c = a.a + a.b;
                  a.b = a.c + a.a;
                  a.a = a.b - a.c;

...

                  b.c(b.a() + b.b());
                  b.b(b.c() + b.a());
                  b.a(b.b() - b.c());




Results:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
Total Math on fields: 430ms
Total Math on buffer: 711ms
Performance difference factor: 1.6534884

Total Math on fields: 381ms
Total Math on buffer: 315ms
Performance difference factor: 0.8267717

Total Math on fields: 268ms
Total Math on buffer: 328ms
Performance difference factor: 1.2238806

Total Math on fields: 245ms
Total Math on buffer: 329ms
Performance difference factor: 1.3428571

Total Math on fields: 248ms
Total Math on buffer: 319ms
Performance difference factor: 1.2862903

Total Math on fields: 251ms
Total Math on buffer: 334ms
Performance difference factor: 1.3306773

Total Math on fields: 255ms
Total Math on buffer: 335ms
Performance difference factor: 1.3137255

Total Math on fields: 254ms
Total Math on buffer: 328ms
Performance difference factor: 1.2913386




Isn't this enough performance?

33% performance loss, without changing the VM, without using Unsafe
Only 22% performance loss when running with -Xcomp


 Grin

Note that this is done with the Sun server VM 1.5.0_05

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 816
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #28 - Posted 2005-10-21 11:48:10 »

Benchmark code:

it does:

for(8x)
{
   long aTook = 0;
   long bTook = 0;

   for(4x)
   {
     // init values

     for(1M x)
        run 4 blocks of math on ClazzA and measure the result
      aTook += tDiff;

     for(1M x)
        run 4 blocks of math on ClazzB and measure the result
      bTook += tDiff;

     // compare values
   }

   // print aTook & bTook
}


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
         int classes = 64;
         ClazzA[] cA = new ClazzA[classes];
         ClazzB[] cB = new ClazzB[classes];

         for (int i = 0; i < classes; i++)
         {
            cA[i] = new ClazzA();
            cB[i] = new ClazzB();
         }

         //

         int loop = 1024 * 1024;

         for (int p = 0; p < 8; p++)
         {
            long tA = 0;
            long tB = 0;

            for (int k = 0; k < 4; k++)
            {
               // init
               for (int i = 0; i < classes; i++)
               {
                  ClazzA a = cA[i % classes];
                  ClazzB b = cB[i % classes];

                  a.a = 5; a.b = 4; a.c = 3; a.x = 1.0F; a.y = 1.1F; a.z = 1.2F;
                  b.a(5); b.b(4); b.c(3); b.x(1.0F); b.y(1.1F); b.z(1.2F);
               }

               // calc
               long t0A = System.nanoTime();
               for (int i = 0; i < loop; i++)
               {
                  ClazzA a = cA[i % classes];

                  a.c = a.a + a.b;                  a.b = a.c + a.a;                  a.a = a.b - a.c;
                  a.c = a.a + a.b;                  a.b = a.c + a.a;                  a.a = a.b - a.c;
                  a.c = a.a + a.b;                  a.b = a.c + a.a;                  a.a = a.b - a.c;
                  a.c = a.a + a.b;                  a.b = a.c + a.a;                  a.a = a.b - a.c;

                  a.z = a.x + a.y;                  a.y = a.z + a.x;                  a.x = a.y - a.z;
                  a.z = a.x + a.y;                  a.y = a.z + a.x;                  a.x = a.y - a.z;
                  a.z = a.x + a.y;                  a.y = a.z + a.x;                  a.x = a.y - a.z;
                  a.z = a.x + a.y;                  a.y = a.z + a.x;                  a.x = a.y - a.z;
               }
               long t1A = System.nanoTime();

               long t0B = System.nanoTime();
               for (int i = 0; i < loop; i++)
               {
                  ClazzB b = cB[i % classes];

                  b.c(b.a() + b.b());                  b.b(b.c() + b.a());                  b.a(b.b() - b.c());
                  b.c(b.a() + b.b());                  b.b(b.c() + b.a());                  b.a(b.b() - b.c());
                  b.c(b.a() + b.b());                  b.b(b.c() + b.a());                  b.a(b.b() - b.c());
                  b.c(b.a() + b.b());                  b.b(b.c() + b.a());                  b.a(b.b() - b.c());

                  b.z(b.x() + b.y());                  b.y(b.z() + b.x());                  b.x(b.y() - b.z());
                  b.z(b.x() + b.y());                  b.y(b.z() + b.x());                  b.x(b.y() - b.z());
                  b.z(b.x() + b.y());                  b.y(b.z() + b.x());                  b.x(b.y() - b.z());
                  b.z(b.x() + b.y());                  b.y(b.z() + b.x());                  b.x(b.y() - b.z());
               }
               long t1B = System.nanoTime();

               // validate
               if (false)
               {
                  for (int i = 0; i < classes; i++)
                  {
                     ClazzA a = cA[i % classes];
                     ClazzB b = cB[i % classes];

                     boolean errorI = (a.a != b.a()) || (a.b != b.b()) || (a.c != b.c());
                     boolean errorF = (a.x != b.x()) || (a.y != b.y()) || (a.z != b.z());

                     if (errorI || errorF)
                        throw new IllegalStateException("Error @ " + i);
                  }
               }

               tA += ((t1A - t0A) / 1000000);
               tB += ((t1B - t0B) / 1000000);
            }

            System.out.println();
            System.out.println("Total Math on fields: " + tA + "ms");
            System.out.println("Total Math on buffer: " + tB + "ms");
            System.out.println("Performance difference factor: " + (float) tB / tA);
         }

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Mark Thornton

Senior Duke





« Reply #29 - Posted 2005-10-21 12:51:31 »

Riven, what changed between your current post and the rather slower performance shown on the initial post (before editing)?
Pages: [1] 2 3
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (50 views)
2014-10-17 03:59:02

Norakomi (39 views)
2014-10-16 15:22:06

Norakomi (31 views)
2014-10-16 15:20:20

lcass (36 views)
2014-10-15 16:18:58

TehJavaDev (66 views)
2014-10-14 00:39:48

TehJavaDev (65 views)
2014-10-14 00:35:47

TehJavaDev (55 views)
2014-10-14 00:32:37

BurntPizza (72 views)
2014-10-11 23:24:42

BurntPizza (43 views)
2014-10-11 23:10:45

BurntPizza (84 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!