4

I work on a program that performs matrix and vector operation in Java. The multiple function call and object creation that occurs in my current implementation makes it sluggish and difficult to understand.

For instance I want to update the position of a mechanical point, by speed integration:

void update(Vector3 position, Vector3 speed, float dt){
   Vector3 displacement = new Vector3(speed);
   displacement.assignMul(dt);
   position.assignAdd(displacement);
}

Here the API is not natural, and in addition I need to allocate an build a new Vector3 reference. Obviously i measured a great performance improvement on real uses case when inlining the computation this way:

void update(Vector3 position, Vector3 speed, float dt){
   position.x += speed.x * dt;
   position.y += speed.y * dt;
   position.z += speed.z * dt;
}

Is there any tool that could generate this code from a domain specific language on demand? A Cog like syntax would be nice. (Cog is a code generation tool from Ned Batchelder)

void update(Vector3 position, Vector3 speed, float dt){
   // [[[DSL position += speed * dt ]]] 
   position.x += speed.x * dt;//Generated Code
   position.y += speed.y * dt;//Generated Code
   position.z += speed.z * dt;//Generated Code
   // [[[END]]]
}
I82Much
  • 26,901
  • 13
  • 88
  • 119
Pierre
  • 545
  • 5
  • 14
  • Why over-complicate a simple operation like matrix / vector math with code generation? What are the goals you are seeking to achieve? Performance & Readability? Consistency? Simplicity? – mellamokb Apr 28 '11 at 13:31
  • 1
    I choose here a trivial example, the real usecases are not so simple. The first goal is the software performance. This one can be achieved by inlining myself every math operation, without any code generation. The second goal is to enhance readability of the code. – Pierre Apr 28 '11 at 13:36
  • As you say you gain a lot of performance in the second code example. However, this not merely a simple inline that you perform. I guess that what you want is quite complicated. Did you look at http://projectlombok.org/? Maybe you could construct an AST for your calculation in java code, which at compiletime you rewrite to your second example. – Alessandro Vermeulen Apr 30 '11 at 22:16
  • 1
    I was too late for adding a link to what I mean to my previous comment, but take a look at: https://gist.github.com/950045 – Alessandro Vermeulen Apr 30 '11 at 22:26
  • @Alessandro that's a nice proposal, it allows to bypass the code generation process if needed, and it allows to leverage code analysis tools and re-factoring tools. – Pierre May 02 '11 at 14:29
  • @user282026, in addition to rewriting the code to the form used in the gist one could also lift the mentioned functions to functions that construct an expression instead of performing the calculation. Then you could optimize the expression either at dynamically or statically. Or you could do the same but by looking at the AST of the expression itself, this might be more difficult as you have to take into account the whole Java language, instead of your specialized Vector DSL. – Alessandro Vermeulen May 04 '11 at 13:28

1 Answers1

1

If you're heart set on code generation, I would highly recommend the book Language Implementation Patterns by Terence Parr. He shows how you would create an abstract syntax tree (AST) based of your DSL and then use rewrite rules to generate code.

Furthermore, he uses a vector DSL as one of his examples, including showing how you can distribute constant multiplications in the syntax tree. e.g.Simplification of a vector DSL.  Page 141 of Language Implementation Patterns by Terence Parr

The relevant section to you would be Chapter 15, Tree Pattern Matcher.

I agree with some of the other posters that this might be a little heavy weight for your purposes. Are you sure you can't implement a more fluent interface as @Alessandro Vermeulen showed in his gist comment? The speed differences look pretty negligible.

I82Much
  • 26,901
  • 13
  • 88
  • 119
  • Strictly speaking, this is a little more than inlining, cause all the computation is made from local variable, and there is not more allocation to store intermediary result. I'm going to post there a real example with benchmarks. – Pierre May 02 '11 at 15:14