Search |
|||
Rémi Forax's blogThe tales of the four Fibonacci'sPosted by forax on November 1, 2009 at 5:17 AM PST
Let me introduce a new language named pseudo (Why this name ?
Why another language ? Why God ? all these questions will be answered
in a later blog).
any is similar to java.lang.Object in Java, but don't require any narrow cast (casts are implicit) and any is also a super type of all primitive types. In fact, in pseudo, there is no distinction between reference types and primitive types. any is equivalent to C# 4.0 dynamic but it's implementation requires, I think, less boxing and less conversions that its C# counterpart. Status of the language
pseudo will run on the upcoming Java 7 platform, a Java platform
that enables JSR 292 i.e a Java platform with the new bytecode instruction invokedynamic.
def fib(n) {
if (n < 2) {
return n
}
return fib(n - 1) + fib(n - 2)
}
public static java.lang.Object fib(java.lang.Object) throws java.lang.Throwable;
Code:
0: aload_0
1: iconst_2
2: invokedynamic #2, 0 // NameAndType "__operator__:<":(Ljava/lang/Object;I)Z
7: ifeq 12
10: aload_0
11: areturn
12: aload_0
13: iconst_1
14: invokedynamic #3, 0 // NameAndType "__operator__:-":(Ljava/lang/Object;I)Ljava/lang/Object;
19: invokestatic #4 // Method fib:(Ljava/lang/Object;)Ljava/lang/Object;
22: aload_0
23: iconst_2
24: invokedynamic #3, 0 // NameAndType "__operator__:-":(Ljava/lang/Object;I)Ljava/lang/Object;
29: invokestatic #4 // Method fib:(Ljava/lang/Object;)Ljava/lang/Object;
32: invokedynamic #5, 0 // NameAndType "__operator__:+":(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
37: areturn
As you see, if you see something, most calls are translated into invokedynamic, but not all of them.
recursive call to fib are translated into invokestatic.
So even in a dynamic language, some part of the code are not dynamic at all.
As I said in the introduction, pseudo is a language that allows gradual typing,
You can, by example, indicates that the parameter of fib is an int.
def fib(int n) {
if (n < 2) {
return n
}
return fib(n - 1) + fib(n - 2)
}
public static java.lang.Object fib(int) throws java.lang.Throwable;
Code:
0: iload_0
1: iconst_2
2: if_icmpge 10
5: iload_0
6: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
9: areturn
10: iload_0
11: iconst_1
12: isub
13: invokestatic #3 // Method fib:(I)Ljava/lang/Object;
16: iload_0
17: iconst_2
18: isub
19: invokestatic #3 // Method fib:(I)Ljava/lang/Object;
22: invokedynamic #4, 0 // NameAndType "__operator__:+":(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
27: areturn
Wow, only the + between the two recursive calls of fib is dynamic.
Also not that n (local variable 0) at bytecode 6 is boxed to be an Integer.
def fib(n):int {
if (n < 2) {
return n
}
return fib(n - 1) + fib(n - 2)
}
public static int fib(java.lang.Object) throws java.lang.Throwable;
Code:
0: aload_0
1: iconst_2
2: invokedynamic #2, 0 // NameAndType "__operator__:<":(Ljava/lang/Object;I)Z
7: ifeq 17
10: aload_0
11: invokedynamic #3, 0 // NameAndType __cast__:(Ljava/lang/Object;)I
16: ireturn
17: aload_0
18: iconst_1
19: invokedynamic #4, 0 // NameAndType "__operator__:-":(Ljava/lang/Object;I)Ljava/lang/Object;
24: invokestatic #5 // Method fib:(Ljava/lang/Object;)I
27: aload_0
28: iconst_2
29: invokedynamic #4, 0 // NameAndType "__operator__:-":(Ljava/lang/Object;I)Ljava/lang/Object;
34: invokestatic #5 // Method fib:(Ljava/lang/Object;)I
37: iadd
38: ireturn
Compared to the full dynamic version, the only optimisation here is that the + between the two fib calls
can be computed using iadd instead of relying on a dynamic call.
Moreover, a dynamic cast was added to convert n as an int at instruction 11.
def fib(int n):int {
if (n < 2) {
return n
}
return fib(n - 1) + fib(n - 2)
}
public static int fib(int) throws java.lang.Throwable;
Code:
0: iload_0
1: iconst_2
2: if_icmpge 7
5: iload_0
6: ireturn
7: iload_0
8: iconst_1
9: isub
10: invokestatic #2 // Method fib:(I)I
13: iload_0
14: iconst_2
15: isub
16: invokestatic #2 // Method fib:(I)I
19: iadd
20: ireturn
The generated code is exactly the same that the one generated by javac for a static method fib written in Java. No dynamic call at all. Benchmark
No blog entry is really a good blog entry without a benchmark :)
result time
fib : 102334155 3,62 s
fib-param : 102334155 3,05 s
fib-return : 102334155 3,42 s
fib-typed : 102334155 1,52 s
First, using a dynamic language have a cost at runtime.
Using a partially typed language reduce the overhead a bit but
the cost of boxing/unboxing is still there.
Cheers, »
Related Topics >>
Blogs J2SE Java Specification Request Open JDK Performance Programming Virtual Machine Comments
Comments are listed in date ascending order (oldest first)
|
CategoriesArchivesNovember 2009
October 2009 September 2009 August 2009 July 2009 June 2009 May 2009 April 2009 February 2009 January 2009 December 2008 November 2008 October 2008 September 2008 July 2008 May 2008 April 2008 March 2008 February 2008 January 2008 November 2007 October 2007 September 2007 August 2007 July 2007 June 2007 May 2007 March 2007 February 2007 January 2007 December 2006 November 2006 October 2006 September 2006 August 2006 July 2006 Recent Entries |
||
|
|