(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