From: Anamitra B. <ana...@ya...> - 2009-12-09 04:34:58
|
Hi I beleive I have found a major issue with the jsr223 implementation of jython in 2.5.1 release - one that would cause huge issues with multithreading. I have a simple script "c=a+b" - which can be tested as a jython script or a rhino [javascript] script. The sample jsr223 code for this is as below: ScriptEngineManager factory = new ScriptEngineManager(); ScriptEngine engine = factory.getEngineByName("python"); CompiledScript cs = ((Compilable)engine).compile("c=a+b"); Ideally I would like to cache this "cs" object and use it in a multithreaded environment. So the next few lines of the code would be executed in a multithreaded env Bindings binding = cs.getEngine().createBindings();//new SimpleBindings(); binding.put("a", a); binding.put("b", b); cs.eval(binding); System.out.println(a+"+"+b+"="+binding.get("c")); Now if I try this with the jython 2.5.1 jar it blows up right in "cs.eval(binding)" statement!!!!! [note I tried with the Bindings binding = new SimpleBindings(); - same error] javax.script.ScriptException: NameError: name 'a' is not defined in <script> at line number 1 at org.python.jsr223.PyScriptEngine.scriptException(PyScriptEngine.java: 182) at org.python.jsr223.PyScriptEngine.eval(PyScriptEngine.java:43) at org.python.jsr223.PyScriptEngine.access$100(PyScriptEngine.java:20) at org.python.jsr223.PyScriptEngine$PyCompiledScript.eval(PyScriptEngine .java:211) at javax.script.CompiledScript.eval(CompiledScript.java:86) Now if this same code is run with rhino [the default that comes with sun/ibm jdk] it works great. If I tweak this code to as below Bindings binding = cs.getEngine().createBindings();//new SimpleBindings(); binding.put("a", a); binding.put("b", b); ScriptContext sc = cs.getEngine().getContext(); sc.setBindings(binding, ScriptContext.ENGINE_SCOPE); cs.eval(sc);//instead of the binding System.out.println(a+"+"+b+"="+binding.get("c")); This works great for jython - but messes up the multithreading entorely as now the Binding is really a part of the ScriptEngine => which is shared by all threads. So in effect I cannot use the CompiledScript in a multithreaded way for jython. This [multithreaded CompliedScript] works for Rhino and this is a very basic expectation - I hope somebody from Jython jsr team is polling this newsgrp to verify my claim. Is this a known bug? Did anybody face this before and knows workaround for this - I am little desparate as without this support I cannot use the CompiledScript concept => wihtout which the jython performance is pretty bad for me. Any pointers is highly appreciated. thanks Anamitra |
From: Nicholas R. <nj...@il...> - 2009-12-09 08:34:37
|
In article <866...@we...>, Anamitra Bhattacharyya <ana...@ya...> wrote: > Bindings binding = cs.getEngine().createBindings();//new SimpleBindings(); > binding.put("a", a); > binding.put("b", b); > cs.eval(binding); > System.out.println(a+"+"+b+"="+binding.get("c")); > > Now if I try this with the jython 2.5.1 jar it blows up right in > "cs.eval(binding)" statement!!!!! [note I tried with the Bindings binding = > new SimpleBindings(); - same error] Yes, modifying a ScriptContext is currently unsupported. You can read a bit more about it in issue 1426, which has been pending for a while: <http://bugs.jython.org/issue1426> > sc.setBindings(binding, ScriptContext.ENGINE_SCOPE); And it seems you've figured out how to work around this. > This [multithreaded CompliedScript] works for Rhino and this is a very basic > expectation - I hope somebody from Jython jsr team is polling this newsgrp to > verify my claim. Is this a known bug? Did anybodyÝface this before and knows > workaround for this - I am little desparate as without this support I cannot > use the CompiledScript concept => wihtout which the jython performance is > pretty bad for me. How much isolation are you expecting between threads? Note that JSR 223 defines several different threading models. From SCR.4.3.5.2: > Multithreaded Engine > Multi-threaded Evaluation - The implementation of the API and the > engine itself are capable of supporting concurrent evaluations by > multiple threads on a single engine instance. However the exact > behavior of such concurrent execution is ultimately determined by the > script or scripts themselves. An engine which supports concurrent > execution is "multi-threaded" in the same sense that the Java language > is "multi-threaded": Evaluation by concurrent threads is allowed and > produces side effects that can be seen by other threads. The threads > may interact or not interact, utilize synchronization or not utilize > synchronization, in scripting language dependent ways. > Thread-Isolated Engine > Satisfies the requirements for Multithreaded. Also, the side-effects > for threads are isolated from one another. Specifically, the isolation > limits the visibility of changes to the state of variables in the engine > scope of the interpreter. Each thread will effectively have its own > thread-local engine scope for the engine instance. Note that this does > not limit the visibility of side effects outside the engine scope for > example, mutation of application-level Java objects. > Stateless Engine > Satisfies the requirements for Thread-Isolated. In addition, the > mappings in the Bindings used as the engine scope of the > ScriptEngine are not modified by any ScriptExecution. The keys in > the Bindings and their associated values are exactly the same before > and after each script execution. The Jython engine is currently implemented as a multithreaded engine. For some limited values of "isolated" it would be possible to implement a thread-isolated engine. Take a look at the code of the Jython engine (PyScriptEngine) and the underlying PythonInterpreter - each is a relatively thin wrapper and should make clear what's going on. You could implement a simple form of thread isolation (for locals/globals) with the functionality in ParserFacade/Py (e.g., see PythonInterpreter.compile). If this is insufficient for your needs, you could go further by creating multiple PySystemState instances. -- Nicholas Riley <nj...@il...> |
From: Anamitra B. <ana...@ya...> - 2009-12-09 17:21:45
|
Hi Nicholas thanks for your quick respponse - I read through the bug description - and pardon my ignorance on this aspect of jsr223 .. I did print the "THREADING" support for jython and it gave me this - MULTITHREADED <code> System.out.println(engine.getFactory().getParameter("THREADING")); </code> Now my expectation was "MULTITHREADED" => the execution is thread safe -> which apparently was not right from ur snippet of the jsr spec. Now all I am trying to do is : The scripts [writtent in jython and any other jsr 223 compliant engine] would be executed from a servlet [=> multi user environment] and each script would take in a bunch of IN spit out bunch of OUT params. For performance I would like to use the CompiledScript object and I was hoping I can just compile the script [provided the underlying engine supports that feature] and cache that object in memory. So the script is hot and when a request comes all I do is compliedSctipt.eval(binding) where the binding object has been created like as below Binding binding = new SimpleBinding(); binding.put("in_param1", value1); binding.put("in_param2", value2); and after the eval call Object out_param1 = binding.get("out_param1"); Object out_param2 = binding.get("out_param2"); Now this request for eval would come simultaneously from multiple threads -> so I need this compliedScript.eval(binding) call to be thread safe -> without needing to synchronize as I am expecting 1000s of Web users for my system and each script can be pretty intensive one - so I cannot do a synchronized access for performance reasons. So when I test this simple script c=a+b - the test code looks like as below [simulating mutiple threads] Note I would like to use the evalParams method - but evalParams bombs for jython - so I use evalParamsThatWorksWtihJython instead. And the output would show u how the thread messes everything up. The output u see there are nulls!! - and if I just change the code to System.out.println(a+"+"+b+"="+cs.getEngine().get("c")); - u sould see 4+5=13 and 2+3=9 etc instead of nulls. BTW the rhino implementation says its "MULTITHREADED" too and still is giving correct out for this test. So do you think what I am trying to do is not valid as per the jsr 223 spec? OR there is some problem with the jython implementation of jsr223. Because if its the former - then I will have to use a pool of CompiledScript objects and that significantly complicates the implementation. If its the latter then I am ready to make an exception for jython and code to the jython api ditching jsr223 for jython - if u say the jython apis [PythonInterpreter etc] would work for this. All I want to achieve is - 1>compile a script and cache it 2>have multiple threads execute that and I use the Binding object as my transport for IN and OUT params to the script. public static void main(String[] args) throws Exception { new MyThread(2,3).start();//a=2 and b=3 - thread will loop 20 times new MyThread(4,5).start();//a=4 and b=5 - thread will loop 20 times new MyThread(6,7).start();//a=6 and b=7 - thread will loop 20 times } public static void evalParams(int a, int b) throws Exception//works for Rhino in this test { Bindings binding = cs.getEngine().createBindings();//new SimpleBindings(); binding.put("a", a); binding.put("b", b); cs.eval(binding); System.out.println(a+"+"+b+"="+binding.get("c")); } public static void evalParamsThatWorksWtihJython(int a, int b) throws Exception { Bindings binding = cs.getEngine().createBindings();//new SimpleBindings(); binding.put("a", a); binding.put("b", b); ScriptContext sc = cs.getEngine().getContext(); sc.setBindings(binding, ScriptContext.ENGINE_SCOPE); cs.eval(sc); System.out.println(a+"+"+b+"="+binding.get("c")); } static class MyThread extends Thread { int i = 1; int j = 1; MyThread(int a, int b) { i = a; j = b; } public void run() { for(int k=0;k<20;k++) { try { evalParams(i,j); } catch(Exception e) { e.printStackTrace(); } } } } ------------output------------------ 6+7=13 2+3=null 6+7=13 2+3=5 6+7=13 2+3=5 6+7=13 4+5=null 2+3=5 6+7=13 2+3=5 6+7=13 4+5=9 6+7=13 2+3=5 6+7=13 2+3=5 6+7=13 2+3=5 6+7=13 2+3=5 6+7=13 2+3=5 4+5=9 2+3=null 6+7=9 2+3=5 4+5=9 2+3=null 2+3=5 4+5=9 6+7=13 2+3=5 6+7=13 2+3=5 2+3=5 4+5=9 2+3=null 4+5=9 6+7=13 2+3=5 6+7=13 2+3=5 6+7=13 6+7=13 6+7=13 4+5=9 6+7=13 4+5=9 4+5=9 4+5=9 4+5=9 4+5=9 4+5=9 4+5=9 4+5=9 4+5=9 4+5=9 4+5=9 4+5=9 thanks Anamitra --- On Wed, 12/9/09, Nicholas Riley <nj...@il...> wrote: From: Nicholas Riley <nj...@il...> Subject: Re: [Jython-users] bug in jython jsr223 implemetation? To: jyt...@li... Date: Wednesday, December 9, 2009, 3:33 AM In article <866...@we...>, Anamitra Bhattacharyya <ana...@ya...> wrote: > Bindings binding = cs.getEngine().createBindings();//new SimpleBindings(); > binding.put("a", a); > binding.put("b", b); > cs.eval(binding); > System.out.println(a+"+"+b+"="+binding.get("c")); > > Now if I try this with the jython 2.5.1 jar it blows up right in > "cs.eval(binding)" statement!!!!! [note I tried with the Bindings binding = > new SimpleBindings(); - same error] Yes, modifying a ScriptContext is currently unsupported. You can read a bit more about it in issue 1426, which has been pending for a while: <http://bugs.jython.org/issue1426> > sc.setBindings(binding, ScriptContext.ENGINE_SCOPE); And it seems you've figured out how to work around this. > This [multithreaded CompliedScript] works for Rhino and this is a very basic > expectation - I hope somebody from Jython jsr team is polling this newsgrp to > verify my claim. Is this a known bug? Did anybodyÝface this before and knows > workaround for this - I am little desparate as without this support I cannot > use the CompiledScript concept => wihtout which the jython performance is > pretty bad for me. How much isolation are you expecting between threads? Note that JSR 223 defines several different threading models. From SCR.4.3.5.2: > Multithreaded Engine > Multi-threaded Evaluation - The implementation of the API and the > engine itself are capable of supporting concurrent evaluations by > multiple threads on a single engine instance. However the exact > behavior of such concurrent execution is ultimately determined by the > script or scripts themselves. An engine which supports concurrent > execution is "multi-threaded" in the same sense that the Java language > is "multi-threaded": Evaluation by concurrent threads is allowed and > produces side effects that can be seen by other threads. The threads > may interact or not interact, utilize synchronization or not utilize > synchronization, in scripting language dependent ways. > Thread-Isolated Engine > Satisfies the requirements for Multithreaded. Also, the side-effects > for threads are isolated from one another. Specifically, the isolation > limits the visibility of changes to the state of variables in the engine > scope of the interpreter. Each thread will effectively have its own > thread-local engine scope for the engine instance. Note that this does > not limit the visibility of side effects outside the engine scope for > example, mutation of application-level Java objects. > Stateless Engine > Satisfies the requirements for Thread-Isolated. In addition, the > mappings in the Bindings used as the engine scope of the > ScriptEngine are not modified by any ScriptExecution. The keys in > the Bindings and their associated values are exactly the same before > and after each script execution. The Jython engine is currently implemented as a multithreaded engine. For some limited values of "isolated" it would be possible to implement a thread-isolated engine. Take a look at the code of the Jython engine (PyScriptEngine) and the underlying PythonInterpreter - each is a relatively thin wrapper and should make clear what's going on. You could implement a simple form of thread isolation (for locals/globals) with the functionality in ParserFacade/Py (e.g., see PythonInterpreter.compile). If this is insufficient for your needs, you could go further by creating multiple PySystemState instances. -- Nicholas Riley <nj...@il...> ------------------------------------------------------------------------------ Return on Information: Google Enterprise Search pays you back Get the facts. http://p.sf.net/sfu/google-dev2dev _______________________________________________ Jython-users mailing list Jyt...@li... https://lists.sourceforge.net/lists/listinfo/jython-users |
From: Nicholas R. <nj...@il...> - 2009-12-09 18:54:20
|
In article <462...@we...>, Anamitra Bhattacharyya <ana...@ya...> wrote: > System.out.println(a+"+"+b+"="+cs.getEngine().get("c")); - u sould see 4+5=13 > and 2+3=9 etc instead of nulls. BTW the rhino implementation says its > "MULTITHREADED" too and still is giving correct out for this test. So do you > think what I am trying to do is not valid as per the jsr 223 spec? OR there > is some problem with the jython implementation of jsr223. Because if its the > former - then I will have to use a pool of CompiledScript objects and that > significantly complicates the implementation. If its the latter then I am > ready to make an exception for jython and code to the jython api ditching > jsr223 for jython - if u say the jython apis [PythonInterpreter etc] would > work for this. All I want > to achieve is - > > 1>compile a script and cache it > 2>have multiple threads execute that and I use the Binding object as my > transport for IN and OUT params to the script. It's just a problem with the Jython implementation the JSR 223 (and PythonInterpreter, for that matter) front ends. There's nothing in Jython itself that stops this from working. At the time I was working on the JSR 223 implementation, I didn't understand the use case you are describing. Now I do and I'll handle it. If you can wait a couple of weeks I will get it fixed, otherwise I suggest you just create your own per-thread locals/global Python dictionaries (which are what the Bindings end up getting mapped to) and use them. If you look at the source code for PythonInterpreter it should be clear what to do, otherwise please ask on the list. -- Nicholas Riley <nj...@il...> |
From: Anamitra B. <ana...@ya...> - 2009-12-09 19:33:38
|
Hi Nicholas that's great - I can definitely wait for couple of weeks - I would be more than willing to test the code that you fix whenever u are ready with it. I will try to code as per we discussed then [not having to implement a pool of CompiledScript is a great relief]. Thanks for your help - do pls let me know whenever u have it ready for a test. thanks Anamitra --- On Wed, 12/9/09, Nicholas Riley <nj...@il...> wrote: From: Nicholas Riley <nj...@il...> Subject: Re: [Jython-users] bug in jython jsr223 implemetation? To: jyt...@li... Date: Wednesday, December 9, 2009, 1:53 PM In article <462...@we...>, Anamitra Bhattacharyya <ana...@ya...> wrote: > System.out.println(a+"+"+b+"="+cs.getEngine().get("c")); - u sould see 4+5=13 > and 2+3=9 etc instead of nulls. BTW the rhino implementation says its > "MULTITHREADED" too and still is giving correct out for this test. So do you > think what I am trying to do is not valid as per the jsr 223 spec? OR there > is some problem with the jython implementation of jsr223. Because if its the > former - then I will have to use a pool of CompiledScript objects and that > significantly complicates the implementation. If its the latter then I am > ready to make an exception for jython and code to the jython api ditching > jsr223 for jython - if u say the jython apis [PythonInterpreter etc] would > work for this. All I want > to achieve is - > > 1>compile a script and cache it > 2>have multiple threads execute that and I use the Binding object as my > transport for IN and OUT params to the script. It's just a problem with the Jython implementation the JSR 223 (and PythonInterpreter, for that matter) front ends. There's nothing in Jython itself that stops this from working. At the time I was working on the JSR 223 implementation, I didn't understand the use case you are describing. Now I do and I'll handle it. If you can wait a couple of weeks I will get it fixed, otherwise I suggest you just create your own per-thread locals/global Python dictionaries (which are what the Bindings end up getting mapped to) and use them. If you look at the source code for PythonInterpreter it should be clear what to do, otherwise please ask on the list. -- Nicholas Riley <nj...@il...> ------------------------------------------------------------------------------ Return on Information: Google Enterprise Search pays you back Get the facts. http://p.sf.net/sfu/google-dev2dev _______________________________________________ Jython-users mailing list Jyt...@li... https://lists.sourceforge.net/lists/listinfo/jython-users |
From: Anamitra B. <ana...@ya...> - 2010-01-07 16:55:37
|
Hi Nicholas By any chance do you have anything that I can test - I have the jython 2.5.1 jar. If you have the modified class files I can just add them in my local and do the test. thanks Anamitra --- On Wed, 12/9/09, Anamitra Bhattacharyya <ana...@ya...> wrote: From: Anamitra Bhattacharyya <ana...@ya...> Subject: Re: [Jython-users] bug in jython jsr223 implemetation? To: jyt...@li..., "Nicholas Riley" <nj...@il...> Date: Wednesday, December 9, 2009, 2:33 PM Hi Nicholas that's great - I can definitely wait for couple of weeks - I would be more than willing to test the code that you fix whenever u are ready with it. I will try to code as per we discussed then [not having to implement a pool of CompiledScript is a great relief]. Thanks for your help - do pls let me know whenever u have it ready for a test. thanks Anamitra --- On Wed, 12/9/09, Nicholas Riley <nj...@il...> wrote: From: Nicholas Riley <nj...@il...> Subject: Re: [Jython-users] bug in jython jsr223 implemetation? To: jyt...@li... Date: Wednesday, December 9, 2009, 1:53 PM In article <462...@we...>, Anamitra Bhattacharyya <ana...@ya...> wrote: > System.out.println(a+"+"+b+"="+cs.getEngine().get("c")); - u sould see 4+5=13 > and 2+3=9 etc instead of nulls. BTW the rhino implementation says its > "MULTITHREADED" too and still is giving correct out for this test. So do you > think what I am trying to do is not valid as per the jsr 223 spec? OR there > is some problem with the jython implementation of jsr223. Because if its the > former - then I will have to use a pool of CompiledScript objects and that > significantly complicates the implementation. If its the latter then I am > ready to make an exception for jython and code to the jython api ditching > jsr223 for jython - if u say the jython apis [PythonInterpreter etc] would > work for this. All I want > to achieve is - > > 1>compile a script and cache it > 2>have multiple threads execute that and I use the Binding object as my > transport for IN and OUT params to the script. It's just a problem with the Jython implementation the JSR 223 (and PythonInterpreter, for that matter) front ends. There's nothing in Jython itself that stops this from working. At the time I was working on the JSR 223 implementation, I didn't understand the use case you are describing. Now I do and I'll handle it. If you can wait a couple of weeks I will get it fixed, otherwise I suggest you just create your own per-thread locals/global Python dictionaries (which are what the Bindings end up getting mapped to) and use them. If you look at the source code for PythonInterpreter it should be clear what to do, otherwise please ask on the list. -- Nicholas Riley <nj...@il...> ------------------------------------------------------------------------------ Return on Information: Google Enterprise Search pays you back Get the facts. http://p.sf.net/sfu/google-dev2dev _______________________________________________ Jython-users mailing list Jyt...@li... https://lists.sourceforge.net/lists/listinfo/jython-users -----Inline Attachment Follows----- ------------------------------------------------------------------------------ Return on Information: Google Enterprise Search pays you back Get the facts. http://p.sf.net/sfu/google-dev2dev -----Inline Attachment Follows----- _______________________________________________ Jython-users mailing list Jyt...@li... https://lists.sourceforge.net/lists/listinfo/jython-users |
From: Nicholas R. <nj...@il...> - 2010-01-21 01:09:50
|
To anyone else who's been following this thread, I think I have a patch that should resolve the ScriptContext/Bindings issues. It is <http://bugs.jython.org/file757/thread_locals.patch> (based on current Jython trunk). Please post comments (and preferably a failing test case if you can write one) on the bug if you have any: <http://bugs.jython.org/issue1426> -- Nicholas Riley <nj...@il...> |