-
-
Notifications
You must be signed in to change notification settings - Fork 402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hang on calculating a large number #538
Comments
Can reproduce. It's threaded, so I guess the reason this freezes is the GIL. We need to see how we can optimize .calc or prevent calculations with such big numbers. |
Maybe before running the calculation, calculate a computational complexity |
I suggest adding adding constraints on maximum magnitudes of inputs to exponential operations like multiplication and division. Something like 10**1000 could be reasonable. Exponentiation needs an additional constraint. Maybe something like |
I've prepared a basic fix for this issue which simply spawns a seperate process and kills it I'm sure there's stuff to imporove here. Let me know what you think. |
@saelo Have you tested this? How does it fare when a big calculation is spammed? It's no good if the host can be flooded with python processes, with each one trying to alloc gigabytes of memory to do the calculation. Something like (2100)(2**100) can allocate quite a bit of memory in a few seconds. |
@Venti- yeah, I've tested it and it's definately not perfect but at least prevents the bot from disconnecting due to timeout. I've ran ~20 huge calculations at the same time on a raspberry pi, the bot is a lot slower during that time but recovers. |
While your solution works, I don't really like the idea of spinning up new python processes just to do a simple computation (something computers are supposed to be pretty good at), so I implemented my own suggestion from earlier. I made the limits quite liberal so you might be able to break it if you try. I based them on how long the calculations took on my laptop and set the limit on around 0.5s. I figured that should be low enough for something like Raspberry to be able to do them in 5s. You could test that though by running the following script on your Raspberry: Here is a script to print a table of how long pow takes for various arguments around the 1s mark:
Here are the result on my laptop (i7-2670QM): x=exp, y=num
|
I guess we should still ad a overall time limit to the evaluator to avoid cases where some complex expression is chained enough times to cause a significant delay. I first thought that the limited input length would take care of that, but with a slow enough processor and the right expression it probably is still a problem. Setting an overall time limit in the evaluator while the individual operations are limited in time should take care of that though. I will do that later today or tomorrow. I also noticed that for large expressions the most time can actually go to turning the 10**9 digit number into characters, which is why I set a limit on the magnitude of numbers than can be returned. Another way to handle that might be to print just the magnitude and a few digits for large numbers. |
Sure, works for me.
For the record here is the output of your script from an RPI (overclocked at 900MHz):
|
Yeah. Python 3 doesn't have longs, but I think comparing against numbers.Integral should do the job. |
- Added default timeout of 5s to expression evaluator, that will throw an error before evaluating the next statement if the timeout has passed. This should stop an expression consisting of several long running statements from taking too long. - Calc now uses general number formatting from str.format to print the number according to it's magnitude. - Fixes bug in Python 2 from #538, where long ints are let through by using abstract base class numbers.Integral.
From looking at your results it's seems like the default limit does indeed limit the runtime to roughly 5s on the pi. I guess you could scale the limit function by timing some calculation at initialization time or something, but I think I'm done with this for now. |
- Fixes sopel-irc#538. - Removed the drivel from calc when exceptions are raised. Printing the actual error might not be pretty, but at least it's not completely useless.
- Added default timeout of 5s to expression evaluator, that will throw an error before evaluating the next statement if the timeout has passed. This should stop an expression consisting of several long running statements from taking too long. - Calc now uses general number formatting from str.format to print the number according to it's magnitude. - Fixes bug in Python 2 from sopel-irc#538, where long ints are let through by using abstract base class numbers.Integral.
It seems to be trivially easy to cause the bot to hang.
".calc 99999999999**9"
hung for several minutes, and was maxing out a core on my server
The text was updated successfully, but these errors were encountered: