|
From: <bc...@wo...> - 2002-01-09 11:02:59
|
>> >> Pros:
>> >> - We will save a pointer for each instance of PyInstance and
>> >> PyJavaInstance and an instance of a CollectionProxy for each Vector,
>> >> Hashtable, Map, etc.
>> >>
>> >> Cons:
>> >> - A serie of instanceof operations is necessary every time one of
>> >> the sequence method is called on a java instance.
>> >
>> >I would think it would be more straight forward to keep the
>> >CollectionProxy's as they are now even though it requires an extra
>> >instance. While the number of Collection classes is small it still
>> >*feels* better to avoid a big if block of instanceof calls.
>>
>> It would be the same two blocks of instanceof operations that you can
>> already find in CollectionProxy*.java. I suggest that we execute these 5
>> if statement for each __len__ and __XXXitem__ call on a java class,
>> instead of executing it just once for each java class and storing the
>> result. The java2 "if" statements would still be located in
>> CollectionProxy2.
[James Northrup]
>sounds like the proposed good ideas are worthy and the idea's proposed
>implementation is awkward.
>
>consider that the great majority of reflection api is native code and the
>blind fragment:
>try{
>o.getClass().getMethod(...).invoke(...)
>}catch(...){...}
>
>is niether unmaintainable nor performance hindered.
Be careful about conclusions about performance. It dependents! The test
program below compiled with jikes-1.15 running on w2k with an AMD 1.3Ghz
yields:
instanceof reflect
javasoft JDK 1.2.1-A 30 2900
javasoft JDK 1.3.1_02 hotspot 2440 3750
javasoft JDK 1.3.1_02 server 2080 3050
javasoft JDK 1.3.1_02 classic 1120 2640
javasoft JDK 1.4 client 2500 760
javasoft JDK 1.4 server 1800 350
IBMjava13 130 4220
So I agree with your performance conclusion, but only for the JDK1.4 VM.
Personally I was quite surprised of the slow instanceof performance for
1.3 and 1.4.
Does anyone know why instanceof on jdk1.3 is so slow compared to 1.2?
>a registry can be built on-the-fly per container class which then houses a
>few methods which are thereafter simply plugged with (instance, Object[])
>parms
>
>classnames and classloaders are going to be final strings. thus the
>registry, a final static hashmap, would be as good as it gets, and meet the
>criterion of stomping blocks of comparison.
Blocks of comparisons does not concern me too much. Look at Py.java2py
and all the __tojava__ methods for loads of other examples.
If the keys in your registry map is classnames, then the names of
subclasses of collection classes must also be added. And removed if the
subclass is unloaded. That can be done by using a weak-key mapping, but
that sound slow.
>given that there is 1 Arrays, 1 collection, 1 map, 1 iterator (2 counting
>ListIterator), and 1 enumeration class, i can see no cause for writing
>per-instance proxies and I question the necesity of per-class proxies. this
>is as orthogonal as java gets and if we perchance write a single final proxy
>class with orthoganal method calls in mind and the occasional random
>reflection probe to categorize a new class entry into its behavior family,
>all is well ever after.
>
>no instanceof calls? no per-object proxy? what if someone calls the wrong
>reflection method on our container object? we let java throw what it will.
Sure.
>I qualify this hint by adding that I know nothing about jython collections
>and proxies and everything about ripping out blocks of comparisons and
>replacing them with factory/registry reflection code.
The if-block or registry-lookup will occur every time a java object is
indexed. So in this case, performance (in both time and memory) is a
little more important than a pleasing design.
regards,
finn
import java.lang.reflect.*;
public class x {
public static final int LOOPS = 3000000;
static int cnt = 0;
public static void main(String args[]) throws Exception {
meassure(new x(), true);
meassure(new x(), true);
meassure(new x(), true);
meassure(new x(), true);
}
public static void meassure(Object o, boolean print)
throws Exception
{
long now;
now = System.currentTimeMillis();
for (int i = 0; i < LOOPS; i++) {
if (o instanceof java.util.Vector) { cnt++; }
if (o instanceof java.util.Dictionary) { cnt++; }
//if (o instanceof java.util.Enumeration) { cnt++; }
if (o instanceof java.util.List) { cnt++; }
if (o instanceof java.util.Collection) { cnt++; }
if (o instanceof java.util.Map) { cnt++; }
//if (o instanceof java.util.Iterator) { cnt++; }
if (o instanceof x) { cnt++; }
}
System.out.println("instanceof " +
(System.currentTimeMillis() - now));
Class xcls = o.getClass();
Method m = xcls.getMethod("call", new Class[0]);
now = System.currentTimeMillis();
for (int i = 0; i < LOOPS; i++) {
m.invoke(o, new Object[0]);
}
System.out.println("reflect " +
(System.currentTimeMillis() - now));
}
public void call() { cnt++; }
}
|