Quantcast

How can I shut down Jython cleanly?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

How can I shut down Jython cleanly?

Tobia Conforto-2
Hello

I'm developing a bridge, based on Jython, to allow the development of J2EE Portlets with the Django framework. I need some advice on how to shut down or reload the Jython interpreter correctly, because right now I'm having some serious memory and thread leaks.

The project includes a Java class and a few Python ones. The Java code implements the Portlet interface and is responsible for creating the Jython interpreter and forwarding all requests to the Python code. In a separate thread it monitors the Python sources for changes, reloading the Jython runtime whenever a change is detected. This class makes extensive use of concurrency tools to support reloading the runtime in the midst of many portlet requests, without any service disruption. The Python code also implements the Portlet interface and is responsible for translating Portlet requests into Django ones and the responses back, working around the differences between the Portlet paradigm and the HTTP one.

But it all hinges on the Jython reloading code, which unfortunately is at the moment very leaky. This is what I do to create an interpreter:

Py.setSystemState(new PySystemState());
PySystemState.initialize(System.getProperties(), configProperties);
jython = new PythonInterpreter();
// cue library imports here

And this is how I destroy it (mostly copied over from org.python.util.jython):

thread.interruptAllThreads();
Py.getSystemState()._systemRestart = true;
try {
    imp.load("socket").__findattr__("_closeActiveSockets").__call__();
} catch (PyException pye) {}
jython.cleanup();
jython = null;

With this code, my test deployment on Tomcat cannot withstand more than a few Jython restarts, after which I get an OutOfMemoryError, usually PermGen space. If I try to manually undeploy the portlet, Tomcat kindly lists the threads and other resources that are being leaked by the Jython interpreter. (see attached file)

My questions to the knowledgeable is thus:

What is the correct way to shut down (or restart, or reset) a Jython interpreter without leaking anything?

I'm using 2.5.2, but I can test dev code if needed.

-Tobia

------------------------------------------------------------------------------
This SF email is sponsosred by:
Try Windows Azure free for 90 days Click Here
http://p.sf.net/sfu/sfd2d-msazure
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users

jython_leaks.txt (6K) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How can I shut down Jython cleanly?

Tobia Conforto-2
Anybody?

Does anybody know how to restart a Jython interpreter without leaks?


> Hello
>
> I'm developing a bridge, based on Jython, to allow the development of
> J2EE Portlets with the Django framework. I need some advice on how to
> shut down or reload the Jython interpreter correctly, because right now
> I'm having some serious memory and thread leaks.
>
> The project includes a Java class and a few Python ones. The Java code
> implements the Portlet interface and is responsible for creating the
> Jython interpreter and forwarding all requests to the Python code. In a
> separate thread it monitors the Python sources for changes, reloading
> the Jython runtime whenever a change is detected. This class makes
> extensive use of concurrency tools to support reloading the runtime in
> the midst of many portlet requests, without any service disruption. The
> Python code also implements the Portlet interface and is responsible for
> translating Portlet requests into Django ones and the responses back,
> working around the differences between the Portlet paradigm and the HTTP
> one.
>
> But it all hinges on the Jython reloading code, which unfortunately is
> at the moment very leaky. This is what I do to create an interpreter:
>
> Py.setSystemState(new PySystemState());
> PySystemState.initialize(System.getProperties(), configProperties);
> jython = new PythonInterpreter();
> // cue library imports here
>
> And this is how I destroy it (mostly copied over from org.python.util.jython):
>
> thread.interruptAllThreads();
> Py.getSystemState()._systemRestart = true;
> try {
>    imp.load("socket").__findattr__("_closeActiveSockets").__call__();
> } catch (PyException pye) {}
> jython.cleanup();
> jython = null;
>
> With this code, my test deployment on Tomcat cannot withstand more than
> a few Jython restarts, after which I get an OutOfMemoryError, usually
> PermGen space. If I try to manually undeploy the portlet, Tomcat kindly
> lists the threads and other resources that are being leaked by the
> Jython interpreter. (see attached file)
>
> My questions to the knowledgeable is thus:
>
> What is the correct way to shut down (or restart, or reset) a Jython
> interpreter without leaking anything?
>
> I'm using 2.5.2, but I can test dev code if needed.
>
> -Tobia


------------------------------------------------------------------------------
Better than sec? Nothing is better than sec when it comes to
monitoring Big Data applications. Try Boundary one-second
resolution app monitoring today. Free.
http://p.sf.net/sfu/Boundary-dev2dev
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How can I shut down Jython cleanly?

claudef
Dear Tobia,

In order to close and clean up a Servlet process under Jython (PyServlet),  I use to move a None value into the larger objects, like arrays and dictionaries and call the garbage collection routine in a manual call, like for example:  
           
            from java.lang import System
            mydictionary = None
            System.gc()

I also use to call the normal servlet close routines (also check eventual exceptions), like:
           stmt.close()  # database statement
             conn.close()  # database driver connection
           out.close()   # servlet output stream
 
In case of any output redirection, restore standard output
              sys.stdout = sys.__stdout__
           _fileObject.close()

This might help to reduce or completely avoid the leaks.

Regards,
Claude

Claude Falbriard
Certified IT Specialist L2 - Middleware
AMS Hortolândia / SP - Brazil
phone:    +55 19 9837 0789
cell:         +55 13 8117 3316
e-mail:    [hidden email]



From:        Tobia Conforto <[hidden email]>
To:        [hidden email]
Date:        05/04/2012 14:19
Subject:        Re: [Jython-users] How can I shut down Jython cleanly?




Anybody?

Does anybody know how to restart a Jython interpreter without leaks?


> Hello
>
> I'm developing a bridge, based on Jython, to allow the development of
> J2EE Portlets with the Django framework. I need some advice on how to
> shut down or reload the Jython interpreter correctly, because right now
> I'm having some serious memory and thread leaks.
>
> The project includes a Java class and a few Python ones. The Java code
> implements the Portlet interface and is responsible for creating the
> Jython interpreter and forwarding all requests to the Python code. In a
> separate thread it monitors the Python sources for changes, reloading
> the Jython runtime whenever a change is detected. This class makes
> extensive use of concurrency tools to support reloading the runtime in
> the midst of many portlet requests, without any service disruption. The
> Python code also implements the Portlet interface and is responsible for
> translating Portlet requests into Django ones and the responses back,
> working around the differences between the Portlet paradigm and the HTTP
> one.
>
> But it all hinges on the Jython reloading code, which unfortunately is
> at the moment very leaky. This is what I do to create an interpreter:
>
> Py.setSystemState(new PySystemState());
> PySystemState.initialize(System.getProperties(), configProperties);
> jython = new PythonInterpreter();
> // cue library imports here
>
> And this is how I destroy it (mostly copied over from org.python.util.jython):
>
> thread.interruptAllThreads();
> Py.getSystemState()._systemRestart = true;
> try {
>    imp.load("socket").__findattr__("_closeActiveSockets").__call__();
> } catch (PyException pye) {}
> jython.cleanup();
> jython = null;
>
> With this code, my test deployment on Tomcat cannot withstand more than
> a few Jython restarts, after which I get an OutOfMemoryError, usually
> PermGen space. If I try to manually undeploy the portlet, Tomcat kindly
> lists the threads and other resources that are being leaked by the
> Jython interpreter. (see attached file)
>
> My questions to the knowledgeable is thus:
>
> What is the correct way to shut down (or restart, or reset) a Jython
> interpreter without leaking anything?
>
> I'm using 2.5.2, but I can test dev code if needed.
>
> -Tobia


------------------------------------------------------------------------------
Better than sec? Nothing is better than sec when it comes to
monitoring Big Data applications. Try Boundary one-second
resolution app monitoring today. Free.
http://p.sf.net/sfu/Boundary-dev2dev
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users



------------------------------------------------------------------------------
Better than sec? Nothing is better than sec when it comes to
monitoring Big Data applications. Try Boundary one-second
resolution app monitoring today. Free.
http://p.sf.net/sfu/Boundary-dev2dev
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How can I shut down Jython cleanly?

Stefan Eletzhofer
In reply to this post by Tobia Conforto-2
Hi,

Am 05.04.2012 um 19:19 schrieb Tobia Conforto:

> Anybody?
>
> Does anybody know how to restart a Jython interpreter without leaks?
>
>

Well, I haven't had the need.  So far, that is.

Have you had a look at the modjy code?  They create a python interpreter
at runtime.

Have you tried 2.5.3b1?  There have been some import bugs fixed there,
maybe this helps wrt. the leakiness …

BTW, are you at the europython in frienze?   Interested in a jython hackathon?

HTH,
Stefan.


--
Stefan Eletzhofer
[hidden email]
http://seletz.github.com


------------------------------------------------------------------------------
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

Re: How can I shut down Jython cleanly?

Tobia Conforto-2
Hi Stefan

> Have you had a look at the modjy code?  They create a python
> interpreter at runtime.

Yes, I have.  Their java class just creates the interpreter once and
never restarts it.  The entire reloading mechanism is done in Python
inside modjy.modjy_publish, with a simple cache of callables.

I'd love to do the same thing, but reloading Django from inside Python
is a mess.  Their own development mode (runserver command) restarts
Python each time it detects a code change, which means spawning
sys.executable if runnig under CPython[1], or raising SystemRestart
under Jython[2].

I just did a benchmark of that machinery, the Jython one, and it leaks
memory just as much as my own code (and probably leaks threads as well).

Just take a random Django project, configure it to run under Jython, and
add a memory sampling view[3], for example with a /ram url.  Then launch
the project (jython manage.py runserver 8080) and do this:

- repeat a few times:
  - call the ram view: curl -s http://localhost:8282/ram
  - touch a project file (for example settings.py or urls.py)
  - wait for the banner in the console, indicating a successful reload

These are the values I get, with a hand-made histogram (% = 3 MB):

Used RAM (median of 11) = 23021952  %%%%%%%
Used RAM (median of 11) = 37697960  %%%%%%%%%%%%
Used RAM (median of 11) = 52303968  %%%%%%%%%%%%%%%%%
Used RAM (median of 11) = 67621720  %%%%%%%%%%%%%%%%%%%%%%
Used RAM (median of 11) = 85631752  %%%%%%%%%%%%%%%%%%%%%%%%%%%%

NOT GOOD!!!

If you just use the project for a time (call other urls) and then call
your /ram url, you don't get such an increase in used ram, at all.

So it appears the way SystemRestart is handled in org.python.util.jython
itself has serious leaks, and that's where I looked for my own code :-(

> Have you tried 2.5.3b1?  There have been some import bugs fixed there,
> maybe this helps wrt. the leakiness...

I just did, and I get the same memory values as above.

> BTW, are you at the europython in frienze? Interested in a jython
> hackathon?

I had not considered going, but a Jython hackathon could be worthwhile!

Cheers,
Tobia


[1] django.utils.autoreload, line 103:

    os.spawnve(os.P_WAIT, sys.executable, args, new_environ)

[2] django.utils.autoreload, line 121:

    from _systemrestart import SystemRestart
    thread.start_new_thread(main_func, args)
    while True:
        if code_changed():
            raise SystemRestart
        time.sleep(1)

[3] Here is my memory sampling view:

    import time
    from java.lang import System, Runtime
    from django.http import HttpResponse

    runtime = Runtime.getRuntime()

    def ram(request):
        '''Run garbage collection and measure the used RAM in Java.
           Sleep for 1s, repeat 11 times and take the median value.'''
        used_ram = []
        for i in range(11):
            System.gc()
            used_ram.append(runtime.totalMemory() - runtime.freeMemory())
            time.sleep(1)
        used_ram.sort()
        return HttpResponse('Used RAM (median of 11) = %d\n' % used_ram[5])


------------------------------------------------------------------------------
For Developers, A Lot Can Happen In A Second.
Boundary is the first to Know...and Tell You.
Monitor Your Applications in Ultra-Fine Resolution. Try it FREE!
http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________
Jython-users mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/jython-users
Loading...