% Getting to Jython 2.7 and Beyond % Jim Baker % jim.baker@{python.org, rackspace.com}
- Implementation of Python for the Java platform
- Compiles to Java bytecode
- Under development since 1997
- Jython 2.7 release candidate 2 now available
- Isn't Jython a dead project?
- Doesn't Jython have a GIL, just like CPython?
- Isn't Jython much slower than other Python implementations?
- Doesn't Jython only implement a subset of Python?
- Isn't Jython a dead project?
- Doesn't Jython have a GIL, just like CPython?
- Isn't Jython much slower than other Python implementations?
- Doesn't Jython only implement a subset of Python?
Answer: No
I have a vested interest:
- Core developer of Jython
- Co-author of Definitive Guide to Jython from Apress
- Committing on Jython since 2007...
- User of Python (including Jython) since 2003
- Software developer at Rackspace
December 2013:
Can Jython be saved or is it pretty much dead at this point?
December 2013:
Can Jython be saved or is it pretty much dead at this point?
July 2014:
So is jython basically dead or what?
December 2013:
Can Jython be saved or is it pretty much dead at this point?
July 2014:
So is jython basically dead or what?
January 2015:
Is it still around? I thought the project was dead :V
From my note to reviewers of this talk proposal:
I assume Jython 2.7.0 will see a final release by the end of this year, and certainly well before PyCon.
Sadly, one last bug precludes this being true. But we were close!
But here is release candidate 2!
$ bin/jython
Jython 2.7rc2+ (default:0213400c518f, Apr 9 2015, 23:01:27)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.7.0_75
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import GIL
$ bin/jython
Jython 2.7rc2+ (default:0213400c518f, Apr 9 2015, 23:01:27)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.7.0_75
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import GIL
File "<stdin>", line 1
SyntaxError: Never going to happen!
$ python2.7 -m test.pystone 1000000
Pystone(1.1) time for 1000000 passes = 8.87509
This machine benchmarks at 112675 pystones/second
$ python2.7 -m test.pystone 1000000
Pystone(1.1) time for 1000000 passes = 8.87509
This machine benchmarks at 112675 pystones/second
vs
$ jython27 -m test.pystone 1000000
Pystone(1.1) time for 1000000 passes = 6.24945
This machine benchmarks at 160014 pystones/second
$ jython -m test.pystone 1000000
Pystone(1.1) time for 1000000 passes = 6.24945
This machine benchmarks at 160014 pystones/second
vs
$ python2.7 -m test.pystone 1000000
Pystone(1.1) time for 1000000 passes = 8.87509
This machine benchmarks at 112675 pystones/second
- Really, pystone??!!!
- Does not consider JVM startup time nor JIT warmup
- Ignores GC issues
Only 21x faster!
$ pypy -m test.pystone 1000000
Pystone(1.1) time for 1000000 passes = 0.29528
This machine benchmarks at 3.38662e+06 pystones/second
- But still, considered that we only focused on compatibility, not bad performance
- Most of the performance improvement from the efforts to improve Java 7 or Java 8
- Actually do care about pystone because it measures some of the costs of dynamic overhead
- Look at the email lists, wikis, code, what's new, bug reports, linked PRs and patches
- And especially the commit log, as guided by the above
- Commits to tell you what has changed
- Not just language features
- Standard library
- Python ecosystem
- Not just language features
- Standard library
- Python ecosystem
How have we responded?
- Python's inventor Guido van Rossum and
- the rest of PythonLabs continues to help
- and support Jython by their understanding
- of how Jython must live with the limits of
- Java.
- Python's inventor Guido van Rossum and
- the rest of PythonLabs continues to help
- and support Jython by their understanding
- of how Jython must live with the limits of
- Java.
Let's not do that!
This change makes it much better:
+ Jython: Python for the Java Platform
+ Jython follows closely the Python language
+ and its reference implementation CPython,
+ as created by Guido van Rossum.
+ Jython 2.7 corresponds to CPython 2.7.
Support we have added:
- six and all of its crazy import hook magic - single source for Python 2 and 3
- characteristic and its class decorator magic
- socket/select/ssl using Netty
- requests and its beautiful API
- pip and setuptools, via ensurepip
- while also support this functionality for Windows
- including executable zip archives
- and on localized platforms, including fixed issues to support Finnish, Japanese, Turkish, and more
- which also means CJK encodings
Demo testing requests on Windows
- Precise integration with Java
- Java can directly import Python modules (at last!)
- Integrates with setuptools to produce jars
- Includes future integration as well with Maven via Aether
- Sprint topic for this week!
from java.io import Serializable
from java.util.concurrent import Callable
class BarClamp(Callable, Serializable):
def call(self):
return 42
To import a Python class that you want to import into Java, add a couple of lines:
from java.io import Serializable
from java.util.concurrent import Callable
from clamp import clamp_base
BarBase = clamp_base("bar") # Java package prefix
class BarClamp(BarBase, Callable, Serializable):
def call(self):
return 42
Key insight: ahead-of-time builds through setuptools to produce a jar for Java linkage:
import ez_setup
ez_setup.use_setuptools()
from setuptools import setup, find_packages
setup(
name = "clamped",
version = "0.1",
packages = find_packages(),
install_requires = ["clamp"],
clamp = ["clamped"],
)
Simply import clamped Python classes into Java code!
import bar.clamped.BarClamp;
public class UseClamped {
public static void main(String[] args) {
BarClamp barclamp = new BarClamp();
try {
System.out.println("BarClamp: " +
barclamp.call());
} catch (Exception ex) {
System.err.println("Exception: " + ex);
}
}
}
Not exactly interesting code!
- Blazing fast WSGI bridge for servlet containers
- Passes standard WSGI tests in
wsgiref.validate
- Sprinting on adding
ServletFilter
support this Friday (April 17) - And uses Clamp!
Add to your web.xml
these config directives:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
...
<servlet>
<servlet-name>fireside</servlet-name>
<servlet-class>
org.python.tools.fireside.servlet.WSGIServlet
</servlet-class>
<init-param>
<param-name>wsgi.handler</param-name>
<param-value>hellowsgi.simple_app</param-value>
</init-param>
</servlet>
Start with
from javax.servlet.http import HttpServlet
from clamp import clamp_base
ToolBase = clamp_base("org.python.tools")
218 lines of code currently
Implement init
method for javax.servlet.http.HttpServlet
:
class WSGIServlet(ToolBase, HttpServlet):
def init(self, config):
application_name = config.getInitParameter(
"wsgi.handler")
parts = application_name.split(".")
if len(parts) < 2 or not all(parts):
raise Exception(...)
module_name = ".".join(parts[:-1])
module = __import__(module_name) # DYNAMIC CODE!
self.application = getattr(module, parts[-1])
self.servlet_environ = dict(BASE_ENVIRONMENT)
self.servlet_environ.update({
"wsgi.errors": AdaptedErrLog(self)
})
Demo project
$ pip install bottle mako
$ pip install \
git+https://github.com/jythontools/clamp.git
$ pip install \
git+https://github.com/jythontools/fireside.git
https://github.com/jimbaker/hellowsgi
from bottle import Bottle, MakoTemplate, route
simple_app = app = Bottle()
hello_template = MakoTemplate(
'<b>Hello ${name}</b>!')
@app.route('/hello/<name>')
def index(name):
return hello_template.render(name=name)
$ jython setup.py install singlejar
$ jar cf hellowsgi.war -C warpack .
$ java -jar jetty-runner.jar hellowsgi.war
$ ab -k -c 20 -n 50000 localhost:8080/hello/world
Percentage of the requests served within a certain time (ms)
50% 2
66% 3
75% 3
80% 4
90% 13
95% 27
98% 46
99% 63
100% 6774 (longest request)
Should fix this startup time!
Percentage of the requests served within a certain time (ms)
50% 1
66% 2
75% 2
80% 2
90% 2
95% 3
98% 3
99% 4
100% 11 (longest request)
So steady state performance is definitely decent
Demo
- Standard project from Java Native Runtime
- Heavily used by JRuby
- Used internally by Jython - example: Posix support
- But not part of standard Python ecosystem
- Idea: simply add JyNI jar to the Java CLASSPATH to enable C extension API support
- Written by Stefan Richthofer
- Now works for a number of packages - tkinter
- Challeng is adding full GC support (!)
- Next steps: ctypes, cffi, ...
- Stefan has applied for GSOC
Consider this simple function:
def f(a):
return a + 1
Results in this code body for function f
:
>>> import dis
>>> import simple
>>> dis.dis(simple.f)
2 0 LOAD_FAST 0 (a)
3 LOAD_CONST 1 (1)
6 BINARY_ADD
7 RETURN_VALUE
case BINARY_ADD:
w = POP();
v = TOP();
if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: int + int */
register long a, b, i;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
/* cast to avoid undefined behaviour
on overflow */
i = (long)((unsigned long)a + b);
if ((i^a) < 0 && (i^b) < 0)
goto slow_add;
x = PyInt_FromLong(i);
}
else if (PyString_CheckExact(v) &&
PyString_CheckExact(w)) {
x = string_concatenate(v, w, f, next_instr);
/* string_concatenate consumed the ref to v */
goto skip_decref_vx;
}
else {
slow_add:
x = PyNumber_Add(v, w);
}
Py_DECREF(v);
skip_decref_vx:
Py_DECREF(w);
SET_TOP(x);
if (x != NULL) continue;
break;
case Opcode.BINARY_ADD: {
PyObject b = stack.pop();
PyObject a = stack.pop();
stack.push(a._add(b));
break;
}
Dive into ceval.c
and PyBytecode.java
- Mostly around performance, Java integration, and of course the usual bug fixes
- Python bytecode compiler for Android, large complex methods
- More hooks for Java integration
- Plan to work on 2.7.x as long as Python 2.7 in wide use
- Time-based releases, not feature-based
- Every 6 months seems reasonable
- Ideally use new workflow CPython is working on
- Java 9 may also add more features to optimize dynamic languages
- Integrating Zippy to provide PyPy-like performance (requires Graal JVM)
Plan to sprint on language support this week:
- Comes up periodically!
- Would be nice for unicode strings and bytestrings to have direct correspondence to Java
- Remove code!
- Release schedule: we will get there at some point!
- But target 3.5 or maybe 3.6 of the Python language