Experimental Scala port

Discuss issues specific the Scala port of Box2D
Zzzzrrr
Posts: 103
Joined: Sat Mar 15, 2008 5:49 am
Location: Washington, DC
Contact:

Re: Experimental Scala port

Postby Zzzzrrr » Thu May 28, 2009 8:13 am

I've added proxyCount and PairCount output data to the testBed, and the results are as expected. The collision detection algorithms appear to be working correctly.

As Villane already mentioned, the performance hit may be originating from the immutable vectors. Each frame there are ~100k-200k Vec2 creations in the Pyramid demo... It would be very interesting to compare the performance with mutable vectors.... maybe we can create a separate branch for testing?

Villane
Posts: 101
Joined: Mon Sep 01, 2008 6:32 am

Re: Experimental Scala port

Postby Villane » Sat May 30, 2009 10:54 am

Ok, I have profiled the shit out of this and am getting nowhere. solvePositionConstraints has more inlining than the Java version, but still appears slower (2-3 times). I added some debugging and as it turns out, the inner loops in that method are being called 2-3 times more than in the Java version. This gets my hopes up that all the performance problems are due to some bug I've made that causes the Scala port to do much more work than necessary.

Tracking down this bug isn't probably easy, though. Any ideas?

Villane
Posts: 101
Joined: Mon Sep 01, 2008 6:32 am

Re: Experimental Scala port

Postby Villane » Sat May 30, 2009 11:55 am

Whoa. Pairs were being created disregarding the correct proxy order (smallest first).

IT'S NOW NEARLY MATCHING THE JAVA VERSION IN PERFORMANCE!!!

Problem solved :)

Villane
Posts: 101
Joined: Mon Sep 01, 2008 6:32 am

Re: Experimental Scala port

Postby Villane » Sat May 30, 2009 12:08 pm

Also, this changes a few things about immutable vectors: less vectors are being created than in the Java version!
(38 M vs. 58 M in one particular test)

Note: this may also be due to more inlining that I've added lately.

Zzzzrrr
Posts: 103
Joined: Sat Mar 15, 2008 5:49 am
Location: Washington, DC
Contact:

Re: Experimental Scala port

Postby Zzzzrrr » Sat May 30, 2009 2:23 pm

Villane wrote:IT'S NOW NEARLY MATCHING THE JAVA VERSION IN PERFORMANCE!!!


Awesome, congrats!!! I'll continue working on the framework gui and tests.

Villane
Posts: 101
Joined: Mon Sep 01, 2008 6:32 am

Re: Experimental Scala port

Postby Villane » Sat May 30, 2009 5:23 pm

Ok, so now that performance is mostly fixed, I think the next things to work on:

* better testbed, with help from zzzzrrr
* some documentation for users (what's different from Box2D/JBox2D, how to run etc.)
* investigating API improvements
* move to Scala 2.8 (coming out this summer or fall, I think)

Scala 2.8 has some interesting changes:

package objects will help us get rid of vecmath.Preamble: importing vecmath._ will also import the implicit conversions and stuff if the implicits are defined in the package object. Maybe MathUtil functions should also be in the vecmath package object, so they appear as top-level functions.

refactored collections: as the new collections are supposed to perform better, maybe we can de-optimize some code to make it cleaner.

default and named parameters for methods: this may be useful for constructing bodies and shapes
http://www.scala-lang.org/sites/default ... d-args.pdf

Zzzzrrr
Posts: 103
Joined: Sat Mar 15, 2008 5:49 am
Location: Washington, DC
Contact:

Performance Timings

Postby Zzzzrrr » Sun May 31, 2009 4:22 pm

While running a few benchmarks I've made an interesting observation in regard to velocity and position iterations. Please excuse me if this has already been discussed in another thread.... One of the significant differences between jBox2D/Scala and the Box2D trunk is how position and velocity iterations are set.

In scalaBox2D and jBox2D, the volocityIterations and positionIterations are set equal. In the Box2D trunk they're separated and individually tuned. In most circumstances, setting positionIterations to 1 or 2 gives visually descent results, and I was under the assumption that fewer position iterations would result in better performance. On the contrary, my pyramid performance tests indicate otherwise. Decreasing the positionIteration count in the pyramid test actually INCREASES the simulation time.

I've adjusted the positionItation count manually in both scalaBox2D and Blaze, and I'm getting the same effect in my performance timings. Has anyone else made this observation?

Zzzzrrr
Posts: 103
Joined: Sat Mar 15, 2008 5:49 am
Location: Washington, DC
Contact:

Re: Performance Timings

Postby Zzzzrrr » Mon Jun 01, 2009 7:07 am

Zzzzrrr wrote:Decreasing the positionIteration count in the pyramid test actually INCREASES the simulation time.


I've thought about this a little more, and the performance is better because the pyramid is going to sleep much sooner with a higher position iteration count. Something to keep in mind when benchmarking.

ewjordan
Posts: 803
Joined: Sun Sep 23, 2007 2:35 pm

Re: Performance Timings

Postby ewjordan » Mon Jun 01, 2009 2:19 pm

Zzzzrrr wrote:I've thought about this a little more, and the performance is better because the pyramid is going to sleep much sooner with a higher position iteration count. Something to keep in mind when benchmarking.

I've thought for a while that it would be good to have a standard benchmarking scene for this reason. I've been using a piston test, which creates a bunch of shapes and keeps them churning by punching them up into the air (code below), but it's not ideal because from what I've noticed after a long enough time it actually explodes (I've never tracked down why, maybe the object masses are too high).

What we'd ideally want is a simple benchmark suite, which individually stress tested each type of shape-shape encounter, as well as different joint types, both with and without bullets enabled, making sure that none of the benchmark tests ever sleep (things should constantly be in motion). If anyone wants to take a shot at that, it would be interesting to see the performance differences between all the ports at various tasks.

FWIW, last time I checked, which was probably a year ago, on my computer the piston test below ran at 470 fps (no drawing) in Java 1.6 with -server enabled, and 710 fps in C++ compiled on OS X with gcc in release mode. I never got around to writing an AS3 or Javascript version. But those numbers are stale anyways, as JBox2d has seen a lot of optimizations since then and Box2d itself has changed significantly (JBox2d is far enough behind the C++ version that at the moment a direct comparison is probably not very meaningful anymore).

Code: Select all

   static final boolean BULLETS = false;
   private RevoluteJoint m_joint1;
   private PrismaticJoint m_joint2;
   
   public void create(World world) {
       {
         // Define crank.
         PolygonDef sd = new PolygonDef();
         sd.setAsBox(0.5f, 2.0f);
         sd.density = 1.0f;

         RevoluteJointDef rjd = new RevoluteJointDef();

         Body prevBody = world.getGroundBody();

         BodyDef bd = new BodyDef();
         bd.position.set(0.0f, 7.0f);
         Body body = world.createBody(bd);
         body.createShape(sd);
         body.setMassFromShapes();

         rjd.initialize(prevBody, body, Vec2.createVec2(0.0f, 5.0f));
         rjd.motorSpeed = 1.0f * 3.1415f;
         rjd.maxMotorTorque = Float.MAX_VALUE;
         rjd.enableMotor = true;
         RevoluteJoint m_joint1 = (RevoluteJoint)world.createJoint(rjd);

         prevBody = body;

         // Define follower.
         sd.setAsBox(0.5f, 4.0f);
         bd.position.set(0.0f, 13.0f);
         body = world.createBody(bd);
         body.createShape(sd);
         body.setMassFromShapes();

         rjd.initialize(prevBody, body, Vec2.createVec2(0.0f, 9.0f));
         rjd.enableMotor = false;
         world.createJoint(rjd);

         prevBody = body;

         // Define piston
         sd.setAsBox(5.0f, 1.5f);
         bd.position.set(0.0f, 17.0f);
         body = world.createBody(bd);
         body.createShape(sd);
         body.setMassFromShapes();

         rjd.initialize(prevBody, body, Vec2.createVec2(0.0f, 17.0f));
         world.createJoint(rjd);

         PrismaticJointDef pjd = new PrismaticJointDef();
         pjd.initialize(world.getGroundBody(), body, Vec2.createVec2(0.0f, 17.0f), Vec2.createVec2(0.0f, 1.0f));

         //pjd.maxMotorForce = Float.MAX_VALUE;
         pjd.enableMotor = false;

         PrismaticJoint m_joint2 = (PrismaticJoint)world.createJoint(pjd);

         // Create a payload
         for (int i=0; i<100; ++i) {
            sd.setAsBox(0.4f,0.3f);
            sd.density = 0.1f;
            bd.position.set(-1.0f, 23.0f + i);
            if (BULLETS) bd.isBullet = true;
            else bd.isBullet = false;
            body = world.createBody(bd);
            body.createShape(sd);
            body.setMassFromShapes();
         }
         
         CircleDef cd = new CircleDef();
         cd.density = 2.0f;
         cd.radius = 0.36f;
         for (int i=0; i<100; ++i) {
            bd.position.set(1.0f, 23.0f + i);
            if (BULLETS) bd.isBullet = true;
            else bd.isBullet = false;
            body = world.createBody(bd);
            body.createShape(cd);
            body.setMassFromShapes();
         }
         
         sd.density = 0.0f;
         sd.friction = 0.0f;
         sd.setAsBox(1.0f, 100.0f);
         bd = new BodyDef();
         bd.position.set(-6.1f,50.0f);
         Body bod = world.createBody(bd);
         bod.createShape(sd);
         bd.position.set(6.1f,50.0f);
         bod = world.createBody(bd);
         bod.createShape(sd);
      }
   }

Villane
Posts: 101
Joined: Mon Sep 01, 2008 6:32 am

Re: Performance Timings

Postby Villane » Mon Jun 01, 2009 2:32 pm

ewjordan wrote:I've thought for a while that it would be good to have a standard benchmarking scene for this reason. I've been using a piston test, which creates a bunch of shapes and keeps them churning by punching them up into the air (code below), but it's not ideal because from what I've noticed after a long enough time it actually explodes (I've never tracked down why, maybe the object masses are too high).


Hey, I was just thinking about this and was going to post a new thread, but then saw your post. :)

But I'm not knowledgeable enough to determine what kind of scene would be best for benchmarking.

Actually, I was also thinking about a headless benchmarking tool that would be able to run tests with any port, which would require each port to:

* implement a small app that runs it from the command line with certain parameter format (for example, run 1000 iterations, run until all bodies fall asleep)
* allow for pauses for profilers to attach
* able to construct a world from a common scene description format
* able to accept some settings in a common format
* report time taken to the standard output in parseable form, so VM startup/warmup times can be excluded.

and maybe
* either report the state of the world in XML or launch a graphical application that displays the state so that it can be examined


Return to “Scala”



Who is online

Users browsing this forum: No registered users and 1 guest