(newbie) java reflection pb


    Feb 09 2006 | 5:13 pm

    • Feb 09 2006 | 5:30 pm
    • Feb 09 2006 | 5:54 pm
      I just found it also. It works like a charm.
      Thanks for the explanations.
      ej
    • Feb 09 2006 | 6:23 pm
      Hi Emmanuel,
      Glad you solved your problem. Since it seems like you are doing this
      for speed reasons, I thought I would mention that I've read that the
      reflection API is very slow. You may want to benchmark these three
      different solutions:
      1. the reflection solution you've already got working,
      2. the if / else switching code you were trying to avoid,
      3. the interface design pattern. Your interface would look something like this:
      public interface ListOperator {
      public float[] operate(float a[], float b[]);
      }
      and the addition class would look something like this:
      public class ListAddition implements ListOperator {
      public float[] operate(float a[], float b[])
      {
      .....
      }
      }
      and then in your MaxObject's constructor you could create an instance
      of the operator requested:
      ListOperator myListOperator;
      public simpleOp(Atom[] args)
      {
      declareIO(2,1);
      myListOperator = new ListAddition();
      }
      and call it like so in your float method:
      public void inlet(float f[])
      {
      if (getInlet() == 1)
      b = f;
      else {
      a = f;
      outlet(0, myListOperator.operate(a,b));
      }
      This is the standard Java design pattern for this type of problem and
      I suspect it will be the fastest.
      Ben
    • Feb 09 2006 | 6:54 pm
      Hi Ben,
      Thanks for the suggestions. I'll try to test the different versions
      soon. But, to be sure I understand correctly, with the interface
      solution, I still need a "big" if/else to do the List operator
      choice, right?
      if (op.equals("+"))
      myListOperator = new ListAddition();
      else if (op.equals("-"))
      myListOperator = new ListSoustraction();
      Best,
      ej
    • Feb 09 2006 | 6:59 pm
      > Thanks for the suggestions. I'll try to test the different versions
      > soon. But, to be sure I understand correctly, with the interface
      > solution, I still need a "big" if/else to do the List operator
      > choice, right?
      yes, but just in the constructor, not in the method that handles incoming lists.
      Another place to look for ideas of how you might set up your code is
      the ListProcessor stuff I made for the initial Max 4.5 release.
      Ben
    • Feb 09 2006 | 7:15 pm
      I also was just reading some stuff that faster reflection is possible
      using the sun.misc.Unsafe class. This class is pretty interesting and
      lives up to its name!
      Topher
    • Feb 09 2006 | 8:10 pm
      > I'll look at it more slowly. Just one thing about this package, I use
      > a lot, is there any possibility to rename list.sum and list.delta in
      > list.Sum and list.Delta. There's just two classes with the first
      > letter un lowercase.
      Yeah, sorry about that. Can't rename them anymore, since they could
      be used in other people's patches, but feel free to rename your local
      copies. :)
      Ben
    • Feb 09 2006 | 8:41 pm
      i am pretty sure you would have to rename and recompile if you take
      that route.
      toph
    • Feb 09 2006 | 10:27 pm
      > i am pretty sure you would have to rename and recompile if you take
      > that route.
      Yes, and change the constructor code to be capitalized. I am so used
      to Eclipse, which would not only rename and modify the code for that
      class appropriately, it would also look through all the projects in
      your workspace to rename the class anywhere else it was used. The
      ability to refactor as easily as that is a big reason I like
      developing in Java.
      Ben
    • Feb 10 2006 | 2:35 pm
    • Feb 10 2006 | 4:30 pm
      > On the list operator problem, I made the different versions (with if,
      > with reflection, with interface).
      > http://www.e--j.com/beta/lop-tests.zip
      >
      > The performances (measured in Max) are quite the same (the interface
      > solution is generally a little bit faster). Is there any better
      > strategy to evaluate the speed of the java code?
      Yes, there is something very important here to understand. When you
      are testing a piece of code for speed it is important to isolate it
      from as much other code as possible. In the test patch that you set
      up, the reason the three Java classes were so close in execution time
      is that the test time was completely dominated by the slow boundary
      crossing between Java and C. In other words, it's very important to
      avoid all inlet and outlet calls when testing various pieces of Java
      code against one another.
      I've attached a new lop-tests.zip. I added an "iterations" attribute
      to each class, I added a calculeResultat() method to each class that
      calculates the result but doesn't output it, and I added an iterate()
      method that uses a for loop to call the calculeResultat() method
      iterations times. I modified the patch so that the same lists were
      sent to all three Java objects, and then the iterate method is called
      on all three.
      To give you an idea of the difference in speed between internal Java
      calculations and the boundary crossing of inlet and outlet calls, with
      your old method 5 iterations were taking about 210 ms on my computer.
      With my new method, 60000 iterations take 254 ms using reflection, 247
      ms using if statements, and only 212 ms using the Interface design
      pattern. So it looks like the Interface design pattern is
      significantly faster.
      But on the other hand - and this is probably the most valuable thing
      to keep in mind when working with Java for small utility objects like
      this - in the context of a patch, the execution time of this object
      will be completely dominated by the input/output boundary crossing
      between Java and C. So unless you're doing a LOT of math in response
      to input messages, it's really not worth the time to highly optimize
      your Java code, because you probably won't notice the difference
      anyway. For example, according to this test using the Interface
      design pattern instead of Reflection will save you 0.7 MICROSECONDS
      every time you want to multiply some lists together.
      To make the most of your Max programming time, write Java code that
      works and is easy to read.
      > The problem with the interface solution is that
      > you get a lot a class files.
      Yeah, I know, this is an unfortunate. One way to deal with this is to
      bundle class files into a JAR file.
      Ben
    • Feb 10 2006 | 6:23 pm
      > the reason the three Java classes were so close in execution time
      > is that the test time was completely dominated by the slow boundary
      > crossing between Java and C.
      i really wish there was something we could do about this. thats why
      i was looking at sun.misc.Unsafe. sigh.
      topher
    • Feb 10 2006 | 6:39 pm
    • Feb 10 2006 | 9:56 pm
      > > the reason the three Java classes were so close in execution time
      > > is that the test time was completely dominated by the slow boundary
      > > crossing between Java and C.
      >
      > i really wish there was something we could do about this. thats why
      > i was looking at sun.misc.Unsafe. sigh.
      Well actually it's not as bad as I thought. :) I took another look at
      Emmanuel's patch and classes. There is an important thing that can
      change to improve the performance by a lot.
      inlet(float[]) and inlet(int[]) are optimized and are faster than
      inlet(Atom[]). I just tested it out, and this small change reduced
      the time taken to process an inlet call by almost 65%. In other
      words, according to my unscientific test inlet(Atom[]) is three times
      slower than inlet(float[]) and inlet(int[]).
      With this trick in place, performance is pretty good. The object
      takes in two lists, processes, and sends out a list in somewhere
      between 20 and 60 microseconds. That includes all the surrounding C
      objects doing their timing work.
      Ben
      ps. outlet(float[]) and outlet(int[]) are similarly optimized over
      outlet(Atom[])
    • Feb 10 2006 | 10:00 pm
      Not really much documentation on this one.
      in the console:
      javap sun.misc.Unsafe
      topher
    • Feb 10 2006 | 10:15 pm
      Cool Ben.
      The inlet stuff explains some other behavior someone was telling me
      about!
      > ps. outlet(float[]) and outlet(int[]) are similarly optimized over
      > outlet(Atom[])
      as are outlet(String msg, float[]), outlet(String msg, int[])!
      Toph
    • Feb 11 2006 | 9:34 am
      Hi,
      > inlet(float[]) and inlet(int[]) are optimized and are faster than
      > inlet(Atom[]). I just tested it out, and this small change reduced
      does the measurements exclude the time for creating Atom[] and int[] ?
      because creating an array of atom of int seams longer than creating an
      int array.
      regards,
      chris
    • Feb 11 2006 | 5:37 pm
      > does the measurements exclude the time for creating Atom[] and int[] ?
      > because creating an array of atom of int seams longer than creating an
      > int array.
      Well yes, because the test was comparing the performance of inlet
      calls. So it is faster for the mxj C code to create an array of ints
      or floats than it is for the code to create an array of Atoms.
      Ben
    • Feb 11 2006 | 6:06 pm
    • Feb 11 2006 | 6:40 pm
      Hi,
      > You mean list(float[] something), don't you?
      Yes, sorry.
      > By the way, I though list method could
      > only accept atoms, as suggest the MaxObject.html.
      Thanks for mentioning this - I see that MaxObject was not updated the
      way it should have been when the optimization for list(float[]) and
      list(int[]) was added. I'll address this shortly.
      Ben