Upload
aubrey-melton
View
213
Download
0
Tags:
Embed Size (px)
Citation preview
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Dynamic Languages and the CLI:IronPython
Jim HuguninMicrosoftCLR Team
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Common Language Infrastructure (CLI) A virtual machine for multiple languages
Shared bytecode Intermediate Language (IL) Common type system Standard features JIT, AOT, GC, reflection, …
International standard ECMA and ISO Several open-source implementations
6 major languages in production use today C#, VB.Net, Managed C++, J#, Eiffel and
COBOL Notably missing are Python, Perl, Scheme, …
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Missing Dynamic Languages“The CLI is, by design, not friendly to dynamic languages.
Prototypes were built, but ran way too slowly.” – InfoWorld, Aug. 2003
"The speed of the current system is so low as to render the current implementation useless for anything beyond demonstration purposes.“ – ActiveState’s report on Python for .NET
How could Microsoft have screwed up so badly that the CLR is far worse than the JVM for dynamic languages?
Jython shows that dynamic languages can run well on the JVM
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
IronPython is… A fast Python implementation for the CLI
Compiles Python source to IL (CLI bytecode) Includes supporting libraries (as managed code) 1.8x faster than Python-2.4 on pystone Runs all of parrotbench at roughly the same speed as
CPython Integrated with the other languages of the CLI
C#, VB, J#, JScript, Cobol, Eiffel, C++, …
An early prototype – version 0.6 Runs pystone and Pie-Thon/parrotbench benchmarks All language features implemented but not well tested A lot of library code to be written or ported Still a few open design questions
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
pystones/second
26K34K
58K
0
10
20
30
40
50
60
70
Python-2.1 Python-2.3 IronPython.NET-1.1
Venerable benchmark
dhrystone in Python in
Lib/test/pystone.py only benchmark
that ships with Python
Simple but non-trivial
~200 lines of code Most basic Python
ops Very little OO
IronPython is fast 1.7x faster than
CPython-2.3 running on .Net-1.1
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
pystones/second Venerable benchmark
dhrystone in Python in Lib/test/pystone.py only benchmark that
ships with Python Simple but non-trivial
~200 lines of code Most basic Python ops Very little OO
IronPython-0.6 is fast 1.7x faster than
CPython-2.3 running on .Net-1.1
1.8x faster than CPython-2.4 running on .Net-2.0beta1
26K34K
58K
38K
67K
0
10
20
30
40
50
60
70
Python-2.1 Python-2.3 IronPython.NET-1.1
Python-2.4 IronPython.NET-2.0b1
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Parrotbench Benchmark “The benchmark here is intended to make Dan
Sugalski's life difficult: there are some standard benchmark thingies (simple random algorithms using basic data types) but also a lot of play with odd corners of the language definition, and Python's extremely dynamic object model: funky descriptors, mutable classes, that sort of thing.” – Guido van Rossum
This is a great benchmark for alternative implementations of Python
It only runs correctly if the implementation can handle the range of dynamic features that make Python what it is
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
IronPython on parrotbench
4% slower than Python-2.3 (need to update)
0 1 2 3 4 5 6 7 8 9
Python-2.3
IronPython
time (seconds)
b0 b1 b2 b3 b4 b5 b6
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Brief parrotbench analysis Half benchmark and half compliance test
Captures the most dynamic extremes This is a great test to have
IronPython is faster on 3 out of 6 tests And tied on 1 of the 6
Performance on both slow tests is dominated by exception handling (but b5 is dominant) throwing and catching an exception is ~3x
slower in IronPython function calls are ~3x faster in IronPython This is the right kind of trade-off
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Maybe the CLI can be great for dynamic languages“IronPython: .NET *is* a good platform for dynamic languages” –
GameDev.Net, March 2004
“Before IronPython, the common wisdom was that it was difficult to make dynamic languages perform well on the CLR.” – Edd Dumbill, July 2004
“There was a meme floating around, a few years ago, that the CLR is inherently unfriendly to dynamic languages. As one of the transmitters of that meme, I'm delighted to be proved wrong.” – Jon Udell, InfoWorld, July 2004
And many, many more of these new comments
What makes the difference?
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
IronPython Architecture
Same architecture as CPython scanner, parser, bytecode generator, support library
Difference is in bytecode and support library Bytecode is IL for the CLR – will produce native code Support lib is written in C# instead of C
Compilation can be static or dynamic Produces .exe/.dll or dynamically load and run
IronPython is now written completely in C# I built 3 prototypes in Python to throw away After I understood the design I moved to C#
PythonSource File
orCode
Snippet
PythonScanner Tokens
PythonParser AST
ILGenerator IL CLR
IronPython.Objects
refs
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Compiling Factorial – to IL
0 LOAD_FAST 0 (n) IL_0000: ldarg.0
3 LOAD_CONST 1 (1) IL_0001: ldsfld object __main__::c$0$PST04000002
6 COMPARE_OP 2 (==) IL_0006: call object IronPython…Ops::Equal(object,object)
9 JUMP_IF_FALSE 8 (to 20) IL_000b: call bool IronPython...Ops::IsTrue(object)IL_0010: brfalse IL_0020
12 POP_TOP
13 LOAD_CONST 1 (1) IL_0015: ldsfld object __main__::c$0$PST04000002
16 RETURN_VALUE IL_001a: ret
def factorial(n): if n == 1: return 1 return n * factorial(n-1)
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Compiling Factorial – to x86
0 LOAD_FAST 0 (n) 0000001b mov edx,dword ptr ds:[01B054E4h] 00000021 mov ecx,esi
3 LOAD_CONST 1 (1)
6 COMPARE_OP 2 (==) 00000023 call dword ptr ds:[036E3184h]
9 JUMP_IF_FALSE 8 (to 20) 00000029 mov edi,eax 0000002b mov ecx,edi 0000002d call dword ptr ds:[036E3084h] 00000033 mov edi,eax 00000035 test edi,edi 00000037 je 00000043
12 POP_TOP
13 LOAD_CONST 1 (1) 00000039 mov eax,dword ptr ds:[01B054E4h]
16 RETURN_VALUE <pop 4 registers and ret>
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Compiling Factorial – to C#def factorial(n): if n == 1: return 1 return n * factorial(n-1)
public static object factorial_f1(object n) { if (Ops.IsTrue(Ops.Equal(n, Main.c_1))) return Main.c_1; return Ops.Multiply(n, Ops.Call(Main.factorial, Ops.Subtract(n, Main.c_1)));}
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Compiling Factorial – to C# v2
def factorial(n): if n == 1: return 1 return n * factorial(n-1)
public static object factorial_f1(object n) { if (Ops.EqualIsTrue(n, 1)) return Main.c_1; return Ops.Multiply(n, Ops.Call(Main.factorial, Ops.Subtract(n, Main.c_1)));}
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Ops.EqualIsTrue
This adds a new fastpath “opcode”
public static bool EqualIsTrue(object x, int y) { if (x is int) return ((int)x) == y;
return IsTrue(Equal(x, y));}
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Compiling Factorial – x86 v2
0 LOAD_FAST 0 (n) 0000001b mov ecx,esi 0000001d mov edx,1 3 LOAD_CONST 1 (1)
6 COMPARE_OP 2 (==) 00000023 call dword ptr ds:[036E3184h]
9 JUMP_IF_FALSE 8 (to 20) 00000028 mov edi,eax 0000002a test edi,edi 0000002c je 00000038
12 POP_TOP
13 LOAD_CONST 1 (1) 00000039 mov eax,dword ptr ds:[01B054E4h]
16 RETURN_VALUE <pop 4 registers and ret>
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Does this affect performance?
Start with a micro-benchmark
def t2(): for i in L: if i == 1000000: break <snip 18 identical lines> if i == 1000000: break
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Does this affect performance?
Millio
ns o
f if tests p
er
seco
nd
7 11 16 1521
69
0
10
20
30
40
50
60
70
80
Python-2.1 Python-2.3 Python-2.4 IronPython on1.1
IronPython on2.0
IronPython on2.0 w/opt
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Does this affect performance? >3x benefit on microbench But what impact on real code? Need to judge cost-benefit tradeoffs
What is the right general version? Just int or int and long or something else? Need to do all 6 comparison ops Dual benefit that it reduces code size and increases
perf in common case However, this reduces perf if the comparison is not
with an int because a new boxed value will need to be created on the fly
FYI – This particular optimization is not in IronPytho-0.6 because it seemed too special purpose
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
How to get good performance Use native CLR constructs whenever possible
Ludicrously optimized machine code But must be used creatively to match Python’s semantics
Create fast-paths for common cases Python scripts to generate C# code at development time Reflection.Emit to generate IL at runtime Some paths might be worth writing by hand Challenge is to figure out what merits a fast-path!
Include fall-backs to fully dynamic implementations General-purpose support for less common cases Handles Python’s fully dynamic semantics
Measure, measure, measure 100’s of small decisions not one large one
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Ease of language experimentation C# is a lot more fun to write than C/C++
And Visual Studio 2005 makes this really nice IL is a lot more fun to write than x86/PowerPC/…
And Reflection.Emit library makes this really simple Performance can be extremely competitive
Can leverage huge effort on core CLR Ease of development plays a significant role here
Some very nice tools CLR Debugger – source debugger for any lang + machine
code peverify – checks for safe IL and generates clear easy to
understand errors for buggy compiler generated IL ildasm/ilasm – nice command-line and GUI IL tools Lutz Roeder’s Reflector – a very nice way to inspect
assemblies Visual Studio 2005
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Integration is more important than performance
Demo
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
A few open design questions How many kinds of strings? i.e. difference
between unicode and ascii? How to handle locals() and
sys._getframe().f_locals? How to interoperate with other dynamic
languages? How to most effectively expose Python code to
other CLR languages
What about unboxed ints like smalltalk and some schemes?
How to support continuations? …
Copyright (c) 2004 Microsoft Corporation, All Rights Reserved
Conclusions The CLI is a great platform for language development Ease of development is key
C# is a lot more fun to write than C/C++ And Visual Studio 2005 makes this really nice
IL is a lot more fun to write than x86/PowerPC/… And Reflection.Emit library makes this really simple
Performance can be extremely competitive Ease of development plays a significant role here
Best effort to date for language interoperability 6 major languages in production today Easy interoperability among these
Tools and libraries are powerful and fun
Why not leverage hundreds of man-years of VM development?