New issue 3023: CPython 3.6.8 faster than PyPy 3.6.1-7.1.1-beta0 https://bitbucket.org/pypy/pypy/issues/3023/cpython-368-faster-than-pypy-361-711-beta0
Cees Timmerman: This performance test should be faster in PyPy according to [https://pypy.org/performance.html](https://pypy.org/performance.html) as it runs Python code \(including SymPy\) multiple times and takes many seconds to complete. ``` """SymPy server by Cees Timmerman, 2019-05-16. Inspired by https://stackoverflow.com/questions/56155624/speeding-up-python-c-call/ """ import re import falcon whitelist = re.compile("(?:[ \d.,<>\[\]()*\/+-]|for|in|Intersection|solveset|S|x|Min|Max|p|Reals)+") def eval_sympy(q): """ Handle stuff like: >>> eval_sympy("Intersection(*[solveset(p, x, S.Reals) for p in [(x > 4.0000), (x < 6.0000), (((x) * 4.0000 + 5.0000) > 5.0000)]])") Interval.open(4.00000000000000, 6.00000000000000) >>> eval_sympy("Intersection(*[solveset(p, x, S.Reals) for p in [(x > 4.0000), (x < 6.0000), ((x * (Min(Max(x, 4.0000), 5.0000))) > 7.0000), ((Min(Max(x, 4.0000), 5.0000)) > 5.0000)]])") EmptySet() >>> eval_sympy("") "Unauthorized string(s): ''" >>> eval_sympy("Min(p)") "ERR: name 'p' is not defined" >>> eval_sympy("1/0") 'ERR: division by zero' >>> eval_sympy("__import__('os').system('clear')") 'Unauthorized string(s): "__im ort__ \\'os\\' system \\'clear\\' "' >>> eval_sympy("().__class__.__bases__[0]") "Unauthorized string(s): ' __class__ __bases__ '" >>> eval_sympy("Max(evil), Min(good)") "Unauthorized string(s): ' evil good '" https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html """ from sympy import Intersection, solveset, S from sympy.abc import x from sympy.functions.elementary.miscellaneous import Min, Max # Whitelist allowed strings. if not re.fullmatch(whitelist, q): return "Unauthorized string(s): %r" % re.sub(whitelist, " ", q) # Blacklist builtins. env = {k:v for (k,v) in locals().items() if not '_' in k} try: return eval(q, env) except Exception as err: return "ERR: {}".format(err) def test_performance(): """Best of 5: Python 3.6.8: local sympy imports: 9.31 s global sympy imports: 9.24 s PyPy 3.6.1-7.1.1-beta0: local sympy imports: 22.93 s global sympy imports: 23.55 s """ import timeit return timeit.timeit("""eval_sympy("Intersection(*[solveset(p, x, S.Reals) for p in [(x > 4.0000), (x < 6.0000), ((x * (Min(Max(x, 4.0000), 5.0000))) > 7.0000), ((Min(Max(x, 4.0000), 5.0000)) > 5.0000)]])")""", number=10, globals=globals()) class SymPyResource: def on_get(self, req, resp): """ >>> from falcon import testing; client = testing.TestClient(api) >>> r = client.simulate_get('/sympy'); r.status_code 200 >>> r.json {'result': "ERR: No 'q' parameter."} >>> client.simulate_get('/sympy?q=Max(1, 2)').json {'result': '2'} """ #q = req.get_param('q', required=True) # Returns <error><title>Missing parameter</title><description>The "q" parameter is required.</description></error> if 'q' in req.params: q = str(req.params['q']) result = {"result": "%s" % eval_sympy(q)} else: result = {"result": "ERR: No 'q' parameter."} resp.media = result api = falcon.API() api.add_route('/sympy', SymPyResource()) if __name__ == '__main__': import sys if "test" in sys.argv: print("Testing Python", sys.version) import doctest result = doctest.testmod(optionflags=doctest.FAIL_FAST if "fast" in sys.argv else 0) # Optionally stop testing after a single failure. print(result) if "perf" in sys.argv: seconds = test_performance() print("%ss" % seconds) sys.exit(seconds > 1) sys.exit(1 if result.failed else 0) from wsgiref import simple_server httpd = simple_server.make_server('127.0.0.1', 8000, api) print("Serving on http://%s:%s/sympy" % httpd.socket.getsockname()) httpd.serve_forever() ``` [https://github.com/CTimmerman/SymPyServer/blob/master/sympy\_server.py](https://github.com/CTimmerman/SymPyServer/blob/master/sympy_server.py) _______________________________________________ pypy-issue mailing list pypy-issue@python.org https://mail.python.org/mailman/listinfo/pypy-issue