Wenn es nach Microsoft ging, gäbe es mehr .NET-Applikationen und somit wären zumindest die Kernbibliotheken von .NET sowieso im Speicher, da wäre der Aufwand neue Programme zu starten gar nicht mal so groß.sma hat geschrieben:Das sich IronPython die Performance mit höherem Speicheraufwand erkauft, sollte klar sein. Ebenso wird die Startzeit bedingt durch die VM-Technologie größer sein - beides ist aber für viele Anwendungen egal, da es dort um länger laufende Prozesse gibt, wo man Speicher und Startzeit gerne gegen zusätzliche Performance tauscht.
IronPython und Mono
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Nachtrag: Im April 2007 hat der Autor CPython 2.5 mit IronPython 1.1 unter Windows vergleichen: ipy = 1,7x cpy.
Zu diesem Zeitpunkt war Mono langsamer als Windows .NET.
Update 1: Hier hat google noch einen Benchmark von Jython 2.3 vs. CPython 2.4 ausgegraben. Jython erreicht 72% der Performance, ist also langsamer. (Ich finde ja nett, dass der Testrechner Cthulhu heißt... Netter Namensraum für Rechner. Wie wäre es mit Shub-Niggurath oder Ghatanothoa...
Update 2: Habe jetzt sebst Pybench für CPython 2.5 und Jython 2.5a1 ausgeführt. Mein Mac hat keinen so schicken Namen, braucht dafür nur ca. 6.3sek für den Benchmark. Jython schlägt sich mit der Java 1.6 64-bit-Server-VM recht gut. Nach einigen Aufwärmrunden liegt die Zeit ebenfalls bei 6.3sek. Dafür braucht Jython aber ~70 MB Hauptspeicher, nicht ~5MB wie CPython. Auch schafft es Jython, 150% CPU-Leistung zu ziehen, während CPy bei 99% bleibt. Java 1.5 Server (32-bit) bringst nicht und bleibt bei etwa 7sek stehen. Dafür braucht es "nur" ~50MB. Java 1.5 Client (32-bit) ist mit 11sek Schlusslicht.
Stefan
Zu diesem Zeitpunkt war Mono langsamer als Windows .NET.
Update 1: Hier hat google noch einen Benchmark von Jython 2.3 vs. CPython 2.4 ausgegraben. Jython erreicht 72% der Performance, ist also langsamer. (Ich finde ja nett, dass der Testrechner Cthulhu heißt... Netter Namensraum für Rechner. Wie wäre es mit Shub-Niggurath oder Ghatanothoa...
Update 2: Habe jetzt sebst Pybench für CPython 2.5 und Jython 2.5a1 ausgeführt. Mein Mac hat keinen so schicken Namen, braucht dafür nur ca. 6.3sek für den Benchmark. Jython schlägt sich mit der Java 1.6 64-bit-Server-VM recht gut. Nach einigen Aufwärmrunden liegt die Zeit ebenfalls bei 6.3sek. Dafür braucht Jython aber ~70 MB Hauptspeicher, nicht ~5MB wie CPython. Auch schafft es Jython, 150% CPU-Leistung zu ziehen, während CPy bei 99% bleibt. Java 1.5 Server (32-bit) bringst nicht und bleibt bei etwa 7sek stehen. Dafür braucht es "nur" ~50MB. Java 1.5 Client (32-bit) ist mit 11sek Schlusslicht.
Stefan
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Super dass mal jemand das wieder getestet hat, schade nur dass ohne IronPython. Aber das könnte man unter Mac wohl nur auf Mono testen. Ales in allem scheint aber IronPython für Linux-Setups generell eher wenig interessant zu sein, denn Mono wird immer noch eine schlechte Performance nachgesagt. :-/ Konkrete Messungen habe ich aber dazu nicht gesehen.
Apropos Java-Benchmarks wäre es generell mal interessant wie sich die verschiedenen Sprachen auf der JVM (etwa JRuby, Jython, Scala, Clojure) bei den gleichen Aufgaben schlagen.
Apropos Java-Benchmarks wäre es generell mal interessant wie sich die verschiedenen Sprachen auf der JVM (etwa JRuby, Jython, Scala, Clojure) bei den gleichen Aufgaben schlagen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Wo finde ich denn die Sourcen für den Benchmark. Vielleicht kann ich hier mal CPython und IronPython (Mono) miteinander vergleichen. Wenn Ich Windows dazu überreden kann IronPython zu verwenden kann ich es da auch mal testen
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Im Python SVN-Tree.burli hat geschrieben:Wo finde ich denn die Sourcen für den Benchmark.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Hm, bei mir spuckt IronPython einen Fehler aus
Code: Alles auswählen
~/pybench$ ipy pybench.py
-------------------------------------------------------------------------------
PYBENCH 2.0
-------------------------------------------------------------------------------
* using Python 2.4.0 (IronPython 1.1.1 (1.1.1) on .NET 2.0.50727.42)
* Python version doesn't support gc.disable
* Python version doesn't support sys.setcheckinterval
* using timer: time.time
* Internal Error (use --debug to display the traceback)
Korrektur: er hat was ausgegeben, aber in der gleichen Farbe wie der Hintergrund. War nicht zu erkennen
Code: Alles auswählen
~/pybench$ ipy pybench.py --debug
-------------------------------------------------------------------------------
PYBENCH 2.0
-------------------------------------------------------------------------------
* using Python 2.4.0 (IronPython 1.1.1 (1.1.1) on .NET 2.0.50727.42)
* Python version doesn't support gc.disable
* Python version doesn't support sys.setcheckinterval
* using timer: time.time
Traceback (most recent call last):
File CommandLine, line unknown, in __init__
File pybench, line unknown, in main
File pybench, line unknown, in __init__
File pybench, line unknown, in __init__
File pybench, line unknown, in get_machine_details
File platform, line unknown, in python_build
File platform, line unknown, in _sys_version
AttributeError: 'NoneType' object has no attribute 'groups'
Ich denke, das ist recht schwer, hier aussagekräftige Benchmarks zu finden. Der Programming Language Shootout kann ein Indiz sein, aber das fehlen Jython und Clojure.Leonidas hat geschrieben:Apropos Java-Benchmarks wäre es generell mal interessant wie sich die verschiedenen Sprachen auf der JVM (etwa JRuby, Jython, Scala, Clojure) bei den gleichen Aufgaben schlagen.
Ich würde tippen, dass Java selbst die Liste anführen würde. Danach kommt dann Scala, was bei gleicher semantischen Komplexität auch in etwa den gleichen Bytecode erzeugen wird und damit von der Laufzeit vergleichbar ist. Hier wäre höchstens interessant, wie viel z.B. eine rein funktionale Lösung an Laufzeit kostet. Ich tippen weiter, dass dann Clojure folgt, welches sich ebenfalls recht stark an den Möglichkeiten bzw. Unmöglichkeiten der JVM orientiert und etwa den Anwender zwingt, auf Rekursion zu verzichten und statt dessen `recur` und `loop` Specialforms einzusetzen. JRuby ist dann schneller als Jython, in erster Linie, weil dort wesentlich mehr Arbeit in die Optimierung geflossen ist. Beide Sprachen wehren sich eigentlich mit Händen und Füßen, in ein so starres Konzept wie die JVM gepresst zu werden und man muss viel Überredungskunst in Form von komplizierten Optimierungen einsetzen, um da etwas zu reißen.
Eine sehr schnelle und dennoch einfache JVM-basierte Scriptsprache ist übrigens Pnuts und Rhino (JavaScript) sollte man auch nicht vergessen. Dann wäre auch ein Blick auf ein echtes Scheme (SISC) oder CommonLisp (ABCL) interessant. Und natürlich darf man Groovy nicht vergessen.
Übrigens, den Ansatz von Cython, also ein Subset von C mit Syntax von Python, welches sich leicht und effizient in C übersetzen lässt aber dennoch für Python-Entwickler eine vertraute Syntax bietet, müsste man doch auch für Java einsetzen können. Ähnlich fing ja Groovy an - man wollte etwas wie Java, das sich aber mit weniger Schmerzen schreiben lässt. Und auch RPython fällt doch in diese Kategorie - ein um dynamische Features beraubtes Subset von Python, welches sich effizient in eine statische Programmiersprache übersetzen lässt.
Stefan
Den Sinn von einer Scriptsprache in einer Scriptsprache verstehe ich eigentlich nicht. Bei IronPython hatte ich mir eigentlich mehr Performance erhofft weil ich dachte Python wird in IML übersetzt und das wird letztendlich nativ compiliert. Aber das war wohl ein Trugschluss. Vielmehr ist wohl der Python Interpreter in C# implementiert
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Also meinst du RPython auf der JVM?sma hat geschrieben:Und auch RPython fällt doch in diese Kategorie - ein um dynamische Features beraubtes Subset von Python, welches sich effizient in eine statische Programmiersprache übersetzen lässt.
Was die Performancereihenfolge angeht hätte ich da ganz ähnlich geschätzt, lediglich Scala habe ich mir nicht ausreichend angesehen und da schätzen zu können. Was aber die Limitierungen der JVM angeht hat Rich Hickey (die treibende Kraft hinter Clojure) meiner Meinung nach noch Tail-Call-Optimization in Zukunft nachzuholen denn ``recur`` scheint drangekleistert zu sein, nicht so wie in Scheme. Zudem das Problem eigentlich lösbar ist, denn soweit ich weiß unterstützt Bigloo auf der JVM TCO ohne Probleme. Man muss es eben selbst Optimieren, da die JVM sowas nicht selbst kann, aber es ist nicht ausgeschlossen dass spätere Clojure-Versionen das nachrüsten wenn mehr Interesse da ist.
Da vermischst du etwas.burli hat geschrieben:Den Sinn von einer Scriptsprache in einer Scriptsprache verstehe ich eigentlich nicht. Bei IronPython hatte ich mir eigentlich mehr Performance erhofft weil ich dachte Python wird in IML übersetzt und das wird letztendlich nativ compiliert. Aber das war wohl ein Trugschluss. Vielmehr ist wohl der Python Interpreter in C# implementiert
IronPython-Programme werden (zumindest als ich zuletzt reingeschaut habe) ja auch in IL kompiliert, nur ist dieser Code nicht so einfach wie der entsprechende C# Code und braucht länger in der Ausführung, weil eben bei Python zur Laufzeit mehr passiert.
Der IronPython-Interpreter ist aber weder in Python noch in IL geschrieben. Analog dazu ist der CPython Interpreter in C geschrieben und produziert ebenso Bytecode, nur eben Python-Bytecode.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Aber Python Bytecode wird doch direkt interpretiert. .NET wird zur Laufzeit in nativen Code compiliert, oder?Leonidas hat geschrieben:Der IronPython-Interpreter ist aber weder in Python noch in IL geschrieben. Analog dazu ist der CPython Interpreter in C geschrieben und produziert ebenso Bytecode, nur eben Python-Bytecode.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Ja, durch den JIT-Compiler. Aber das ist keine .NET-Spezialität, das haben die JVM, PLT Scheme, PyPy und viele andere auch.burli hat geschrieben:Aber Python Bytecode wird doch direkt interpretiert. .NET wird zur Laufzeit in nativen Code compiliert, oder?
Fakt ist: auch wenn man den Code zu nativen Code kompiliert, ist es langsamer als C#, schlicht weil eben mehr Code ausgeführt werden muss.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
PyPy ist ein JIT? Das verwirrt mich jetzt weil bei mir pypy ein Python in Python Interpreter istLeonidas hat geschrieben:Ja, durch den JIT-Compiler. Aber das ist keine .NET-Spezialität, das haben die JVM, PLT Scheme, PyPy und viele andere auch.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
PyPy hat einen JIT (AFAIR sogar mehr noch, einen JIT-Generator). PyPy ist weniger ein Interpreter (das auch), sondern mehr eine Compiler-Infrastruktur.burli hat geschrieben:PyPy ist ein JIT? Das verwirrt mich jetzt weil bei mir pypy ein Python in Python Interpreter istLeonidas hat geschrieben:Ja, durch den JIT-Compiler. Aber das ist keine .NET-Spezialität, das haben die JVM, PLT Scheme, PyPy und viele andere auch.
sma, wie ich inzwischen rausgefunden habe, gibt es RPython auf der JVM.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
IronPython übersetzt in IL - genau wie Jython, JRuby, Pnuts, Rhino oder Groovy in Java-Bytecode übersetzen. Über den Stand des einfachen Interpreters sind die alle hinaus. Allerdings bringt das weniger als einem lieb ist, da der JIT jeweils gerade mal eben den Nachteil durch die nicht auf die Sprache zugeschnittene VM-Architektur auszugleichen vermag. Ich erwarte eigentlich, dass MagLev, einem auf einer Smalltalk-VM basierendem Ruby JRuby (und IronRuby) zeigt, wo der Hammer hängt... oder Gemstone-Smalltalk ist richtig schlecht. JVM und VES haben natürlich den Vorteil, dass da 10x mehr Ressourcen in die Entwicklung geflossen sind als bei jeder anderen VM.burli hat geschrieben:Den Sinn von einer Scriptsprache in einer Scriptsprache verstehe ich eigentlich nicht. Bei IronPython hatte ich mir eigentlich mehr Performance erhofft weil ich dachte Python wird in IML übersetzt und das wird letztendlich nativ compiliert. Aber das war wohl ein Trugschluss. Vielmehr ist wohl der Python Interpreter in C# implementiert
JRuby ist ein Spezialfall, da hier der ursprüngliche Ruby-Interpreter so langsam ist, dass fast alles, was man versucht, schneller ist :) Daher gelang es hier, Ruby hinter sich zu lassen. Die Jython-Entwickler werden sich mehr anstrengen müssen, da CPython schon mal grundsätzlich schneller ist. JRuby erkauft sich die schnellere Performance übrigens (genau wie Jython) durch deutlich höheren Speicherverbrauch und eine längere Startphase.
Ansonsten: Eine Scriptsprache ist meist ausdrucksstärker als eine klassische Compiler-Sprache wie C oder Java und das das will man sich bei der Entwicklung von neuen Interpretern zu nutze machen. Hier ist ein Beispiel:
Code: Alles auswählen
for i, r in enumerate(map(lambda n: n * n, range(10))):
print i, r
Code: Alles auswählen
public class Test {
public static void main(String[] args) {
Function<int, int> f = new Function<int, int>() {
public int apply(int n) {
return n * n;
}
};
for (Tuple2<int, int> t : Python.enumerate(Python.map(f, Python.range(10)))) {
int i = t.get(0);
int r = t.get(1);
Python.print(i, r);
}
}
}
Unten stehendes Java-Programm könnte man dabei automatisch aus dem Python-Programm erzeugen - jedenfalls wenn man annimmt, das "int" ausreichend ist und eine ausgefeilte Typanalyse hat, die "Tuple2<int, int>" ermitteln kann. Hier sind die statischen Funktionen, die ich benutzt habe.
Eine einfachere, aber nicht mehr so effiziente Übersetzung wäre, das statisches Typsystem von Java auszuhebeln und überall mit "PyObject"-Exemplaren zu arbeiten, von denen dann "PyInt" eine Unterklasse ist, die Ganzzahlen repräsentiert. das Beispiel könnte dann so aussehen:
Code: Alles auswählen
public static void main(String[] args) {
Function f = new Function() {
public Obj apply(Obj n) {
return n.multiply(n);
}
};
for (Tuple t : Python.enumerate(Python.map(f, Python.range(10)))) {
Obj i = t.get(0);
Obj r = t.get(1);
Python.print(i, r);
}
}
Stefan
Ich habe eben gerade noch ein bisschen gespielt. Ich glaube, das wird jetzt ziemlich OT.
Dieses Java-Programm (notwendiges Laufzeitsystem auf Anfrage) braucht auf meinem Rechner etwa 7ms für fib(28). CPython 2.5 braucht dafür 340ms.
Das Java-Programm ist offensichtlich nicht so flexibel wie Python, denn ich kann z.B. nicht einfach die globale Variable "fib" überschreiben - es gibt sie nicht. Ich kann auch nicht mittels "locals()" auf das "n" zugreifen. Der Kontext in Form von Frame-Objekten existiert ebenfalls nicht.
Sind derartige Funktionen verzichtbar, kann man in einem Subset von Python programmieren, welches sich recht effizient nach Java übersetzen lässt.
Definiere ich fib als Exemplar eine Klasse "Function", beträgt die Laufzeit etwa 8ms. Das ist noch erträglich. Jetzt kann ich "fib" ändern, habe nach wie vor gehen weder locals() noch globals().
Benutze ich ein Dict, um globale Werte zu speichern, bricht mir die Performance auf 33ms (50ms wenn ich die Strings nicht cache und 19ms wenn ich Strings interniere - also einzigartig mache) ein. Ich nutze eine java.util.HashMap als Implementierung.
Baue ich mir ein für diesen Benchmark optimales Dict, welches sich eine Anfrage merkt und bei selben Key den gemerkten Wert liefert und nicht in die java.util.HashMap schaut, komme ich auf 11ms runter.
Benutze ich auch für das lokale "n" ein dict, bin ich bei 340ms. Ahme ich also möglichst genau die Python-Semantik nach, muss ich auch mit Pythons Ausführungszeit leben.
Mit einer speziellen Dict-Implementierung für lokale Variablen kann ich die Zeit nochmal auf 109ms drücken, ich denke aber, das ist nur deswegen so extrem, weil ich in fib nur eine Variable habe. Simuliere ich 4 Variablen, bin ich bei 250ms (200ms bei 3 Variablen).
Führe ich ein Frame-Objekt ein, kann ich dort lokale Variablen verwalten. Das erlaubt, locals(), doch Frame-Objekte müssen jetzt parallel zu Javas normalem direkt in der VM verwalteten Stack von Activations verwaltet werden und ich komme auf 98ms (ThreadLocal-Variable) bzw. 64ms (einfache globale Variable). Eine Alternative, die ich in Smython benutze ist, den Frame überall durchzureichen. Das ist mit 62ms in diesem Beispiel geringfühig schneller. Locals lässt sich dann so implementieren:
Alle Zeiten mit JDK 1.6 64-bit im Sever-Modus gemessen.
Stefan
Dieses Java-Programm (notwendiges Laufzeitsystem auf Anfrage) braucht auf meinem Rechner etwa 7ms für fib(28). CPython 2.5 braucht dafür 340ms.
Code: Alles auswählen
static Obj fib(Obj n) {
if (n.lessThan(_2)) {
return _1;
} else {
return fib(n.subtract(_1)).add(fib(n.subtract(_2)));
}
}
Sind derartige Funktionen verzichtbar, kann man in einem Subset von Python programmieren, welches sich recht effizient nach Java übersetzen lässt.
Definiere ich fib als Exemplar eine Klasse "Function", beträgt die Laufzeit etwa 8ms. Das ist noch erträglich. Jetzt kann ich "fib" ändern, habe nach wie vor gehen weder locals() noch globals().
Code: Alles auswählen
static Function fib = new Function() {
@Override
Obj call(Obj n) {
if (n.lessThan(_2)) {
return _1;
} else {
return fib.call(n.subtract(_1)).add(fib.call(n.subtract(_2)));
}
}
};
Code: Alles auswählen
static Dict globals = Dict();
static {
globals.setItem(s_fib, new Function() {
@Override
Obj call(Obj n) {
if (n.lessThan(_2)) {
return _1;
} else {
return globals.getItem(s_fib).call(n.subtract(_1)).add(globals.getItem(s_fib).call(n.subtract(_2)));
}
}
});
}
Benutze ich auch für das lokale "n" ein dict, bin ich bei 340ms. Ahme ich also möglichst genau die Python-Semantik nach, muss ich auch mit Pythons Ausführungszeit leben.
Mit einer speziellen Dict-Implementierung für lokale Variablen kann ich die Zeit nochmal auf 109ms drücken, ich denke aber, das ist nur deswegen so extrem, weil ich in fib nur eine Variable habe. Simuliere ich 4 Variablen, bin ich bei 250ms (200ms bei 3 Variablen).
Führe ich ein Frame-Objekt ein, kann ich dort lokale Variablen verwalten. Das erlaubt, locals(), doch Frame-Objekte müssen jetzt parallel zu Javas normalem direkt in der VM verwalteten Stack von Activations verwaltet werden und ich komme auf 98ms (ThreadLocal-Variable) bzw. 64ms (einfache globale Variable). Eine Alternative, die ich in Smython benutze ist, den Frame überall durchzureichen. Das ist mit 62ms in diesem Beispiel geringfühig schneller. Locals lässt sich dann so implementieren:
Code: Alles auswählen
new BuiltinFunction() {
@Override
Obj call(Frame frame) {
return frame.back.locals();
}
}
Stefan