Proof of concept PR here <https://github.com/sympy/sympy/pull/8295>. Adding 
a timeout for each function took not that much code, but it seems the 
functions in `fu` are slowed down more by `expand` than anything. 
Continuing to propogate timeout throughout the codebase could work, but I 
don't feel like doing that until I get some validation on the concept.

On Thursday, October 23, 2014 3:06:22 PM UTC-5, James Crist wrote:
>
> What's "composable" in this context? 
>>
>
> Easy to write without intruding too much into the actual function.
>
> That would not affect SymPy itself, as it is not multithreaded. 
>
>
> No, but it would affect anything that tried to run sympy functions that 
> use this in a separate thread. 
>  
>
>> It should work without a problem under Windows - there's no mention that 
>> signal.alarm() does not work on any platform. 
>
>
> From the python documentation: "On Windows, signal() 
> <https://docs.python.org/2/library/signal.html#module-signal> can only be 
> called with SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, or SIGTERM. A 
> ValueError 
> <https://docs.python.org/2/library/exceptions.html#exceptions.ValueError> 
> will be raised in any other case." To use `signal.alarm`, you need to call 
> signal with `SIGALRM`, which is not supported. The test suite is run on 
> travis, which uses ubuntu, so it works there fine.
>
> It's quite intrusive. 
>> It's also going to be broken with every new algorithm, because people 
>> will (rightly) concentrate on getting it right first. 
>
>
> I don't think it's that intrusive (especially with precomposed checking 
> functions). It wouldn't have to be available for every function, and 
> requires very little modification. In the last half hour I've almost 
> finished applying an example of it to `fu`. Didn't take long at all, and 
> requires only a few lines of code changed. Could it be better? Absolutely. 
> I wish there was a way to go about doing this without modifying any of the 
> logic code (simply decorating functions/using a context manager would be 
> ideal). But this doesn't seem to be possible in a crossplatorm/robust way.
>
> I did write up a second option that used a decorator and a contextmanager, 
> but it assumes single-thread application (uses a global TIMEOUT variable :( 
> ). I prefer the method described above.
>
> OT3H letting SymPy functions test for timeout on a regular basis isn't 
>> going to come for free, either.
>
>
> For sure.  However, I don't think the overhead of calling `time.time()` is 
> too large:
>
> In [2]: %timeit time.time()
> 1000000 loops, best of 3: 1.21 µs per loop
>
> Could still be a problem though. This was just a proposal - I'm not 
> adamant that sympy needs such a feature.
>
>
>
>  
>
>
>
> On Thursday, October 23, 2014 2:39:01 PM UTC-5, Joachim Durchholz wrote:
>>
>> Am 23.10.2014 um 20:23 schrieb James Crist: 
>> > However, this isn't the easiest thing to do in Python. The best 
>> > *composable* option 
>>
>> What's "composable" in this context? 
>>
>>  > is to use signal.alarm, which is only available on *NIX 
>> > systems. This can also cause problems with threaded applications. 
>>
>> That would not affect SymPy itself, as it is not multithreaded. 
>> (This, in turn, has its reason in the default Python implementation 
>> having weak-to-nonexistent support for multithreading.) 
>>
>>  > Checks 
>> > for windows 
>>
>> It should work without a problem under Windows - there's no mention that 
>> signal.alarm() does not work on any platform. 
>> In fact the timeout code for the unit tests uses this, and AFAIK it 
>> works well enough. 
>>
>>  > or not running in the main thread could be added to handle this 
>> > though, but would limit it's use. 
>>
>> Actually you'll get a Python exception if you try to set a signal 
>> handler anywhere except in the main thread. Or at least the Python docs 
>> claim so, I haven't tried. 
>>
>> OTOH anybody who wants a timeout on SymPy (or any other piece of Python 
>> code) can set up signal.alarm() themselves. There's simply no need for 
>> SymPy itself to cater for this. 
>>
>> > A second option would be to implement a "pseudo-timeout". This only 
>> works 
>> > for functions that have many calls, but each call is guaranteed to 
>> complete 
>> > in a reasonable amount of time (recursive, simple rules, e.g. `fu`). 
>> The 
>> > timeout won't be exact, but should limit excessively long recursive 
>> > functions to approximately the timeout. I wrote up a quick 
>> implementation 
>> > of this here <https://gist.github.com/jcrist/c451f3bdd6d038521a12>. It 
>> > requires some function boilerplate for each recursive call that *can't* 
>> be 
>> > replaced with a decorator. However, it's only a few lines per function. 
>> I 
>> > think this is the best option if we were to go about adding this. 
>>
>> It's quite intrusive. 
>> It's also going to be broken with every new algorithm, because people 
>> will (rightly) concentrate on getting it right first. 
>> This means we'll always have a list of algorithms that do this kind of 
>> cooperative multitaking less often than we'd like. 
>>
>> There's an alternative: sys.trace(). I'm not sure what kind of overhead 
>> is assocated with that (depending on implementation specifics, it could 
>> be quite big). 
>> OT3H letting SymPy functions test for timeout on a regular basis isn't 
>> going to come for free, either. People will always have to find the 
>> right middle ground between checking too often (slowdown) or too rarely 
>> (unresponsive). 
>>
>> So... my best advice (not necessarily THE best advice) would be to leave 
>> this to people who call SymPy. 
>>
>> BTW here's the timeout code in sympy/utilities/runtest.py: 
>>      def _timeout(self, function, timeout): 
>>          def callback(x, y): 
>>              signal.alarm(0) 
>>              raise Skipped("Timeout") 
>>          signal.signal(signal.SIGALRM, callback) 
>>          signal.alarm(timeout)  # Set an alarm with a given timeout 
>>          function() 
>>          signal.alarm(0)  # Disable the alarm 
>> It's noncomposable (it assumes exclusive use of SIGALRM), and it's 
>> strictly limited to being run in the main thread. That said, it has been 
>> working really well, and maybe the best approach would be to document it 
>> and point people with timeout needs towards it - those who use Stackless 
>> or whatever real multithreading options are out there will be able to 
>> use a better timeout wrapper, so this should be the least intrusive way 
>> to deal with timeout requirements. 
>>
>> just my 2c. 
>> Jo 
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sympy+unsubscr...@googlegroups.com.
To post to this group, send email to sympy@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/547b7c4d-6285-48f0-8736-58146fe29d39%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to