Browse Source

python: Use virtualenv to isolate tests.

INADA Naoki 11 years ago
parent
commit
28cf9580aa
50 changed files with 398 additions and 264 deletions
  1. 109 0
      frameworks/Python/README.md
  2. 4 4
      frameworks/Python/bottle/bash_profile.sh
  3. 8 4
      frameworks/Python/bottle/gunicorn_conf.py
  4. 10 5
      frameworks/Python/bottle/install.sh
  5. 11 15
      frameworks/Python/bottle/setup.py
  6. 11 15
      frameworks/Python/bottle/setup_py3.py
  7. 11 14
      frameworks/Python/bottle/setup_pypy.py
  8. 2 10
      frameworks/Python/django/README.md
  9. 3 3
      frameworks/Python/django/bash_profile.sh
  10. 6 0
      frameworks/Python/django/gunicorn_conf.py
  11. 7 4
      frameworks/Python/django/install.sh
  12. 3 0
      frameworks/Python/django/setup.py
  13. 3 0
      frameworks/Python/django/setup_pg.py
  14. 3 0
      frameworks/Python/django/setup_py3.py
  15. 0 6
      frameworks/Python/falcon/README.md
  16. 3 3
      frameworks/Python/falcon/bash_profile.sh
  17. 6 1
      frameworks/Python/falcon/gunicorn_conf.py
  18. 10 5
      frameworks/Python/falcon/install.sh
  19. 4 1
      frameworks/Python/falcon/setup.py
  20. 8 2
      frameworks/Python/falcon/setup_py3.py
  21. 8 2
      frameworks/Python/falcon/setup_pypy.py
  22. 3 3
      frameworks/Python/flask/bash_profile.sh
  23. 2 2
      frameworks/Python/flask/benchmark_config
  24. 8 2
      frameworks/Python/flask/gunicorn_conf.py
  25. 10 5
      frameworks/Python/flask/install.sh
  26. 0 31
      frameworks/Python/flask/setup.py
  27. 5 1
      frameworks/Python/flask/setup_nginxuwsgi.py
  28. 27 0
      frameworks/Python/flask/setup_py2.py
  29. 10 20
      frameworks/Python/flask/setup_py3.py
  30. 10 28
      frameworks/Python/flask/setup_pypy.py
  31. 3 3
      frameworks/Python/pyramid/bash_profile.sh
  32. 5 0
      frameworks/Python/pyramid/gunicorn_conf.py
  33. 7 4
      frameworks/Python/pyramid/install.sh
  34. 7 4
      frameworks/Python/pyramid/setup_py2.py
  35. 7 4
      frameworks/Python/pyramid/setup_py3.py
  36. 8 19
      frameworks/Python/tornado/README.md
  37. 3 4
      frameworks/Python/tornado/bash_profile.sh
  38. 10 4
      frameworks/Python/tornado/install.sh
  39. 0 19
      frameworks/Python/uwsgi/README.md
  40. 3 3
      frameworks/Python/uwsgi/bash_profile.sh
  41. 10 3
      frameworks/Python/uwsgi/install.sh
  42. 0 2
      frameworks/Python/uwsgi/requirements.txt
  43. 3 2
      frameworks/Python/uwsgi/setup_nginx.py
  44. 3 3
      frameworks/Python/wsgi/bash_profile.sh
  45. 5 0
      frameworks/Python/wsgi/gunicorn_conf.py
  46. 10 3
      frameworks/Python/wsgi/install.sh
  47. 4 1
      frameworks/Python/wsgi/setup.py
  48. 3 0
      frameworks/Python/wsgi/setup_nginxuwsgi.py
  49. 1 0
      toolset/setup/linux/languages/pypy.sh
  50. 1 0
      toolset/setup/linux/languages/python2.sh

+ 109 - 0
frameworks/Python/README.md

@@ -0,0 +1,109 @@
+# Python frameworks
+
+## Experts
+
+* INADA Naoki (@methane) -- Expert of Python and Python's MySQL driver.
+
+
+## Python interpreters
+
+### (C)Python 3
+
+Newest Python.
+
+It will be most major interpreter for Web Development in this or next year.
+This is a bit slower than CPython 2, but more simple and productive than it.
+
+### (C)Python 2
+
+Legacy Python.
+
+It is most major interpreter for now.
+
+### PyPy
+
+PyPy is the fastest Python implementation with JIT.
+
+There is PyPy's Python 3 implementation (PyPy3), but it is not so tuned like PyPy2.
+So we don't use it for now.
+
+
+## WSGI Servers
+
+### Nginx + uWSGI
+
+This is one of fast and realistic way to serve Python web application.
+
+Use unix domain socket between nginx and uWSGI to avoid additional TCP/IP overhead.
+
+
+### Gunicorn + Meinheld
+
+[Meinheld](https://github.com/mopemope/meinheld) is very fast WSGI server.
+
+Since Meinheld is safe against slowloris and support Keep-Alive, you can use it
+without buffered HTTP reverse proxy (like nginx).
+
+We use meinheld to measure bare (without DB access) performance of framework without
+overhead of reverse proxying. (plaintext, json test)
+
+Meinheld does not provide worker process management.
+[Gunicorn](http://gunicorn.org/) provide it for Meinheld.
+
+
+### Gunicorn + Tornado
+
+uWSGI + PyPy is difficult to setup.
+Meinheld doesn't so fast with PyPy because it uses Python/C API heavily.
+So we use Tornado as HTTP/WSGI server.
+
+It supports keep-alive. So it have nice performance about json or plaintext benchmark.
+
+
+## Before writing new tests.
+
+**Don't increase matrix without significant purpose.**
+
+We can't maintain matrix of frameworks (5~) * servers (3~) * DBs (3) * Interpreters (3).
+
+If you want to know about performance difference between MySQL and PostgreSQL,
+there are no need to all frameworks implement both of them.
+Additionally, Python is not a good language to measure performance of DBs because
+web application written in Python is slower than DBs.
+
+If you want to benchmark http server, you should not port all tests or frameworks.
+Simple json or plaintext test is enough.
+
+If your framework uses SQLAlchemy, Flask may be enough to know performance of SQLAlchemy.
+
+
+## Advice when writing new tests
+
+### Interpreter
+
+Consider Python 3 first. -- Python 3 will be mainstream for web development soon.
+
+### Server
+
+Try Gunicorn + Meinheld first. All WSGI apps in this benchmark uses it. You can compare
+your framework performance with others.
+
+### Files you should provide
+
+You can see Flask's files to know how to write new test.
+
+`requirements.txt` is standard way to define depending libraries.
+
+`install.sh` is executed before running test.  You should create virtualenv on `$TROOT/py2`
+(or py3 for Python 3 and pypy for PyPy).  Then `$TROOT/py2/bin/pip install -r requirements.txt`.
+virtualenv is installed on Python 2 and PyPy.  Use `$IROOT/py3/bin/python3 -m venv $TROOT/py3`
+for Python 3.
+
+`bash_profile.sh` is evaluated when running test.  You can set environment variables here.
+
+`bechmark_config` is json file to define test.
+See [here](https://github.com/TechEmpower/FrameworkBenchmarks#the-benchmark_config-file)
+
+`setup_py2.py` is used to run test on Python 2.  `gunicorn_conf.py` is configuration for gunicorn.
+`setup_py2.py` and `gunicorn_conf.py` are written as generic as possible.
+You may be able to use it with changing wsgi callable.  (`$PY2_GUNICORN wsgimodule:callable -c gunicorn_conf.py`)

+ 4 - 4
frameworks/Python/bottle/bash_profile.sh

@@ -1,14 +1,14 @@
-export PY2_ROOT=$IROOT/py2
+export PY2_ROOT=$TROOT/py2
 export PY2=$PY2_ROOT/bin/python
 export PY2=$PY2_ROOT/bin/python
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 
 
-export PYPY_ROOT=$IROOT/pypy
+export PYPY_ROOT=$TROOT/pypy
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 
 
-export PY3_ROOT=$IROOT/py3
+export PY3_ROOT=$TROOT/py3
 export PY3=$PY3_ROOT/bin/python
 export PY3=$PY3_ROOT/bin/python
-export PY3_PIP=$PY3_ROOT/bin/pip3
+export PY3_PIP=$PY3_ROOT/bin/pip
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 8 - 4
frameworks/Python/bottle/gunicorn_conf.py

@@ -1,14 +1,18 @@
 import multiprocessing
 import multiprocessing
+import os
 import sys
 import sys
 
 
 _is_pypy = hasattr(sys, 'pypy_version_info')
 _is_pypy = hasattr(sys, 'pypy_version_info')
-
+_is_travis = os.environ.get('TRAVIS') == 'true'
 
 
 workers = multiprocessing.cpu_count() * 3
 workers = multiprocessing.cpu_count() * 3
+if _is_travis:
+    workers = 2
+
 bind = "0.0.0.0:8080"
 bind = "0.0.0.0:8080"
 keepalive = 120
 keepalive = 120
 errorlog = '-'
 errorlog = '-'
-
+pidfile = 'gunicorn.pid'
 
 
 if _is_pypy:
 if _is_pypy:
     worker_class = "tornado"
     worker_class = "tornado"
@@ -16,7 +20,7 @@ else:
     worker_class = "meinheld.gmeinheld.MeinheldWorker"
     worker_class = "meinheld.gmeinheld.MeinheldWorker"
 
 
     def post_fork(server, worker):
     def post_fork(server, worker):
-        # Disalbe access log
+        # Disable access log.
+        # (Until https://github.com/mopemope/meinheld/pull/42 is released)
         import meinheld.server
         import meinheld.server
         meinheld.server.set_access_logger(None)
         meinheld.server.set_access_logger(None)
-

+ 10 - 5
frameworks/Python/bottle/install.sh

@@ -1,10 +1,15 @@
 #!/bin/bash
 #!/bin/bash
 
 
-mkdir -p ~/.pip_cache
-export PIP_DOWNLOAD_CACHE=$HOME/.pip_cache
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
 
 
 fw_depends python2 python3 pypy nginx
 fw_depends python2 python3 pypy nginx
 
 
-$IROOT/py2/bin/pip install -r $TROOT/requirements.txt
-$IROOT/py3/bin/pip3 install -r $TROOT/requirements.txt
-$IROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt
+$IROOT/py2/bin/virtualenv $TROOT/py2
+$TROOT/py2/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/py3/bin/python3 -m venv $TROOT/py3
+$TROOT/py3/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/pypy/bin/virtualenv $TROOT/pypy
+$TROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt

+ 11 - 15
frameworks/Python/bottle/setup.py

@@ -1,25 +1,21 @@
-import subprocess
 import os
 import os
+import subprocess
+import time
 
 
-
-proc = None
+CWD = os.path.dirname(__file__)
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
-    global proc
-    proc = subprocess.Popen(
-            "exec $PY2_GUNICORN -c gunicorn_conf.py app:app",
-            cwd="bottle", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.Popen(
+        "$PY2_GUNICORN app:app -c gunicorn_conf.py",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
-    global proc
-    if proc is None:
-        return 0
-    proc.terminate()
-    proc.wait()
-    proc = None
-
-    subprocess.call("sudo pkill gunicorn", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call(
+        "kill `cat gunicorn.pid`",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 11 - 15
frameworks/Python/bottle/setup_py3.py

@@ -1,25 +1,21 @@
-import subprocess
 import os
 import os
+import subprocess
+import time
 
 
-
-proc = None
+CWD = os.path.dirname(__file__)
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
-    global proc
-    proc = subprocess.Popen(
-            "exec $PY3_GUNICORN -c gunicorn_conf.py app:app",
-            cwd="bottle", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.Popen(
+        "$PY3_GUNICORN app:app -c gunicorn_conf.py",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
-    global proc
-    if proc is None:
-        return 0
-    proc.terminate()
-    proc.wait()
-    proc = None
-
-    subprocess.call("sudo pkill gunicorn", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call(
+        "kill `cat gunicorn.pid`",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 11 - 14
frameworks/Python/bottle/setup_pypy.py

@@ -1,24 +1,21 @@
-import subprocess
 import os
 import os
+import subprocess
+import time
 
 
+CWD = os.path.dirname(__file__)
 
 
-proc = None
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
-    global proc
-    proc = subprocess.Popen(
-        "exec $PYPY_GUNICORN -c gunicorn_conf.py --error-logfile - app:app",
-        cwd="bottle", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.Popen(
+        "$PYPY_GUNICORN app:app -c gunicorn_conf.py",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
-    global proc
-    if proc is None:
-        return 0
-    proc.terminate()
-    proc.wait()
-    proc = None
-
-    subprocess.call("sudo pkill gunicorn", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call(
+        "kill `cat gunicorn.pid`",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 2 - 10
frameworks/Python/django/README.md

@@ -1,6 +1,6 @@
 # Django Benchmarking Test
 # Django Benchmarking Test
 
 
-This is the Django portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+This is the Django portion of a benchmarking test suite comparing a variety of web development platforms.
 
 
 ### JSON Encoding Test
 ### JSON Encoding Test
 
 
@@ -13,14 +13,6 @@ This is the Django portion of a [benchmarking test suite](../) comparing a varie
 * [DB test model](hello/world/models.py)
 * [DB test model](hello/world/models.py)
 
 
 
 
-## Infrastructure Software Versions
-The tests were run with:
-* [Python 2.7.3](http://www.python.org/)
-* [Django 1.4](https://www.djangoproject.com/)
-* [Gunicorn 0.17.2](http://gunicorn.org/)
-* [MySQL 5.5.29](https://dev.mysql.com/)
-
-
 ## Resources
 ## Resources
 * https://docs.djangoproject.com/en/dev/intro/tutorial01/
 * https://docs.djangoproject.com/en/dev/intro/tutorial01/
 
 
@@ -35,4 +27,4 @@ http://localhost:8080/db
 
 
 ### Variable Query Test
 ### Variable Query Test
 
 
-http://localhost:8080/db?queries=2
+http://localhost:8080/db?queries=2

+ 3 - 3
frameworks/Python/django/bash_profile.sh

@@ -1,14 +1,14 @@
-export PY2_ROOT=$IROOT/py2
+export PY2_ROOT=$TROOT/py2
 export PY2=$PY2_ROOT/bin/python
 export PY2=$PY2_ROOT/bin/python
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 
 
-export PYPY_ROOT=$IROOT/pypy
+export PYPY_ROOT=$TROOT/pypy
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 
 
-export PY3_ROOT=$IROOT/py3
+export PY3_ROOT=$TROOT/py3
 export PY3=$PY3_ROOT/bin/python
 export PY3=$PY3_ROOT/bin/python
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 6 - 0
frameworks/Python/django/gunicorn_conf.py

@@ -1,12 +1,18 @@
 import multiprocessing
 import multiprocessing
+import os
 import sys
 import sys
 
 
 _is_pypy = hasattr(sys, 'pypy_version_info')
 _is_pypy = hasattr(sys, 'pypy_version_info')
+_is_travis = os.environ.get('TRAVIS') == 'true'
 
 
 workers = multiprocessing.cpu_count() * 3
 workers = multiprocessing.cpu_count() * 3
+if _is_travis:
+    workers = 2
+
 bind = "0.0.0.0:8080"
 bind = "0.0.0.0:8080"
 keepalive = 120
 keepalive = 120
 errorlog = '-'
 errorlog = '-'
+pidfile = 'gunicorn.pid'
 pythonpath = 'hello'
 pythonpath = 'hello'
 
 
 if _is_pypy:
 if _is_pypy:

+ 7 - 4
frameworks/Python/django/install.sh

@@ -1,9 +1,12 @@
 #!/bin/bash
 #!/bin/bash
 
 
-mkdir -p ~/.pip_cache
-export PIP_DOWNLOAD_CACHE=$HOME/.pip_cache
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
 
 
 fw_depends python2 python3
 fw_depends python2 python3
 
 
-$IROOT/py2/bin/pip install -r $TROOT/requirements.txt
-$IROOT/py3/bin/pip3 install -r $TROOT/requirements.txt
+$IROOT/py2/bin/virtualenv $TROOT/py2
+$TROOT/py2/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/py3/bin/python3 -m venv $TROOT/py3
+$TROOT/py3/bin/pip install -r $TROOT/requirements.txt

+ 3 - 0
frameworks/Python/django/setup.py

@@ -1,10 +1,12 @@
 import subprocess
 import subprocess
+import time
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PY2_GUNICORN --pid=gunicorn.pid hello.wsgi:application -c gunicorn_conf.py --env DJANGO_DB=mysql",
         "$PY2_GUNICORN --pid=gunicorn.pid hello.wsgi:application -c gunicorn_conf.py --env DJANGO_DB=mysql",
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
@@ -12,4 +14,5 @@ def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
+    time.sleep(3)
     return 0
     return 0

+ 3 - 0
frameworks/Python/django/setup_pg.py

@@ -1,10 +1,12 @@
 import subprocess
 import subprocess
+import time
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PY2_GUNICORN --pid=gunicorn.pid hello.wsgi:application -c gunicorn_conf.py --env DJANGO_DB=postgresql_psycopg2",
         "$PY2_GUNICORN --pid=gunicorn.pid hello.wsgi:application -c gunicorn_conf.py --env DJANGO_DB=postgresql_psycopg2",
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
@@ -12,4 +14,5 @@ def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
+    time.sleep(3)
     return 0
     return 0

+ 3 - 0
frameworks/Python/django/setup_py3.py

@@ -1,10 +1,12 @@
 import subprocess
 import subprocess
+import time
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PY3_GUNICORN --pid=gunicorn.pid hello.wsgi:application -c gunicorn_conf.py --env DJANGO_DB=mysql",
         "$PY3_GUNICORN --pid=gunicorn.pid hello.wsgi:application -c gunicorn_conf.py --env DJANGO_DB=mysql",
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
@@ -12,4 +14,5 @@ def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
         cwd="django", shell=True, stderr=errfile, stdout=logfile)
+    time.sleep(3)
     return 0
     return 0

+ 0 - 6
frameworks/Python/falcon/README.md

@@ -6,12 +6,6 @@ Single file test, [app.py](app.py)
 
 
 Falcon API framework (http://falconframework.org)
 Falcon API framework (http://falconframework.org)
 
 
-### Interpreter
-
-* CPython 2.7
-* CPython 3.3
-* PyPy 2.2
-
 ### Database
 ### Database
 
 
 (none at the moment)
 (none at the moment)

+ 3 - 3
frameworks/Python/falcon/bash_profile.sh

@@ -1,14 +1,14 @@
-export PY2_ROOT=$IROOT/py2
+export PY2_ROOT=$TROOT/py2
 export PY2=$PY2_ROOT/bin/python
 export PY2=$PY2_ROOT/bin/python
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 
 
-export PYPY_ROOT=$IROOT/pypy
+export PYPY_ROOT=$TROOT/pypy
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 
 
-export PY3_ROOT=$IROOT/py3
+export PY3_ROOT=$TROOT/py3
 export PY3=$PY3_ROOT/bin/python
 export PY3=$PY3_ROOT/bin/python
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 6 - 1
frameworks/Python/falcon/gunicorn_conf.py

@@ -1,10 +1,15 @@
 import multiprocessing
 import multiprocessing
+import os
 import sys
 import sys
 
 
 _is_pypy = hasattr(sys, 'pypy_version_info')
 _is_pypy = hasattr(sys, 'pypy_version_info')
+_is_travis = os.environ.get('TRAVIS') == 'true'
 
 
 # falcon only implements json and plain. Not wait DB.
 # falcon only implements json and plain. Not wait DB.
-workers = multiprocessing.cpu_count()
+workers = multiprocessing.cpu_count()  # *3
+if _is_travis:
+    workers = 2
+
 bind = "0.0.0.0:8080"
 bind = "0.0.0.0:8080"
 keepalive = 120
 keepalive = 120
 errorlog = '-'
 errorlog = '-'

+ 10 - 5
frameworks/Python/falcon/install.sh

@@ -1,10 +1,15 @@
 #!/bin/bash
 #!/bin/bash
 
 
-mkdir -p ~/.pip_cache
-export PIP_DOWNLOAD_CACHE=$HOME/.pip_cache
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
 
 
 fw_depends python2 python3 pypy
 fw_depends python2 python3 pypy
 
 
-$IROOT/py2/bin/pip install -r $TROOT/requirements.txt
-$IROOT/py3/bin/pip3 install -r $TROOT/requirements.txt
-$IROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt
+$IROOT/py2/bin/virtualenv $TROOT/py2
+$TROOT/py2/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/py3/bin/python3 -m venv $TROOT/py3
+$TROOT/py3/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/pypy/bin/virtualenv $TROOT/pypy
+$TROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt

+ 4 - 1
frameworks/Python/falcon/setup.py

@@ -1,5 +1,6 @@
-import subprocess
 import os
 import os
+import subprocess
+import time
 
 
 CWD = os.path.dirname(__file__)
 CWD = os.path.dirname(__file__)
 
 
@@ -8,6 +9,7 @@ def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PY2_GUNICORN app:app -c gunicorn_conf.py",
         "$PY2_GUNICORN app:app -c gunicorn_conf.py",
         cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
         cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
@@ -15,4 +17,5 @@ def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
         cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
         cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 8 - 2
frameworks/Python/falcon/setup_py3.py

@@ -1,15 +1,21 @@
+import os
 import subprocess
 import subprocess
+import time
+
+CWD = os.path.dirname(__file__)
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PY3_GUNICORN app:app -c gunicorn_conf.py",
         "$PY3_GUNICORN app:app -c gunicorn_conf.py",
-        cwd="falcon", stderr=errfile, stdout=logfile, shell=True)
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
-        cwd="falcon", stderr=errfile, stdout=logfile, shell=True)
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 8 - 2
frameworks/Python/falcon/setup_pypy.py

@@ -1,15 +1,21 @@
+import os
 import subprocess
 import subprocess
+import time
+
+CWD = os.path.dirname(__file__)
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PYPY_GUNICORN app:app -c gunicorn_conf.py",
         "$PYPY_GUNICORN app:app -c gunicorn_conf.py",
-        cwd="falcon", stderr=errfile, stdout=logfile, shell=True)
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
-        cwd="falcon", stderr=errfile, stdout=logfile, shell=True)
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 3 - 3
frameworks/Python/flask/bash_profile.sh

@@ -1,14 +1,14 @@
-export PY2_ROOT=$IROOT/py2
+export PY2_ROOT=$TROOT/py2
 export PY2=$PY2_ROOT/bin/python
 export PY2=$PY2_ROOT/bin/python
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 
 
-export PYPY_ROOT=$IROOT/pypy
+export PYPY_ROOT=$TROOT/pypy
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 
 
-export PY3_ROOT=$IROOT/py3
+export PY3_ROOT=$TROOT/py3
 export PY3=$PY3_ROOT/bin/python
 export PY3=$PY3_ROOT/bin/python
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 2 - 2
frameworks/Python/flask/benchmark_config

@@ -2,7 +2,7 @@
   "framework": "flask",
   "framework": "flask",
   "tests": [{
   "tests": [{
     "default": {
     "default": {
-      "setup_file": "setup",
+      "setup_file": "setup_py2",
       "json_url": "/json",
       "json_url": "/json",
       "db_url": "/dbs",
       "db_url": "/dbs",
       "query_url": "/db?queries=",
       "query_url": "/db?queries=",
@@ -25,7 +25,7 @@
       "versus": "wsgi"
       "versus": "wsgi"
     },
     },
     "mysql-raw": {
     "mysql-raw": {
-      "setup_file": "setup",
+      "setup_file": "setup_py2",
       "db_url": "/dbsraw",
       "db_url": "/dbsraw",
       "query_url": "/dbraw?queries=",
       "query_url": "/dbraw?queries=",
       "fortune_url": "/fortunesraw",
       "fortune_url": "/fortunesraw",

+ 8 - 2
frameworks/Python/flask/gunicorn_conf.py

@@ -1,12 +1,18 @@
 import multiprocessing
 import multiprocessing
+import os
 import sys
 import sys
 
 
 _is_pypy = hasattr(sys, 'pypy_version_info')
 _is_pypy = hasattr(sys, 'pypy_version_info')
+_is_travis = os.environ.get('TRAVIS') == 'true'
 
 
 workers = multiprocessing.cpu_count() * 3
 workers = multiprocessing.cpu_count() * 3
+if _is_travis:
+    workers = 2
+
 bind = "0.0.0.0:8080"
 bind = "0.0.0.0:8080"
 keepalive = 120
 keepalive = 120
 errorlog = '-'
 errorlog = '-'
+pidfile = 'gunicorn.pid'
 
 
 if _is_pypy:
 if _is_pypy:
     worker_class = "tornado"
     worker_class = "tornado"
@@ -14,7 +20,7 @@ else:
     worker_class = "meinheld.gmeinheld.MeinheldWorker"
     worker_class = "meinheld.gmeinheld.MeinheldWorker"
 
 
     def post_fork(server, worker):
     def post_fork(server, worker):
-        # Disalbe access log
+        # Disable access log.
+        # (Until https://github.com/mopemope/meinheld/pull/42 is released)
         import meinheld.server
         import meinheld.server
         meinheld.server.set_access_logger(None)
         meinheld.server.set_access_logger(None)
-

+ 10 - 5
frameworks/Python/flask/install.sh

@@ -1,10 +1,15 @@
 #!/bin/bash
 #!/bin/bash
 
 
-mkdir -p ~/.pip_cache
-export PIP_DOWNLOAD_CACHE=$HOME/.pip_cache
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
 
 
 fw_depends python2 python3 pypy nginx
 fw_depends python2 python3 pypy nginx
 
 
-$IROOT/py2/bin/pip install -r $TROOT/requirements.txt
-$IROOT/py3/bin/pip3 install -r $TROOT/requirements.txt
-$IROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt
+$IROOT/py2/bin/virtualenv $TROOT/py2
+$TROOT/py2/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/py3/bin/python3 -m venv $TROOT/py3
+$TROOT/py3/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/pypy/bin/virtualenv $TROOT/pypy
+$TROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt

+ 0 - 31
frameworks/Python/flask/setup.py

@@ -1,31 +0,0 @@
-import subprocess
-import os
-import time
-
-proc = None
-
-
-def start(args, logfile, errfile):
-    global proc
-    proc = subprocess.Popen(
-        "exec $PY2_GUNICORN app:app -c gunicorn_conf.py",
-        cwd="flask", stderr=errfile, stdout=logfile, shell=True)
-    return 0
-
-
-def stop(logfile, errfile):
-    global proc
-    if proc is None:
-        return 0
-    proc.terminate()
-    proc = None
-    time.sleep(1)
-
-    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
-    out, err = p.communicate()
-    for line in out.splitlines():
-      if 'gunicorn' in line:
-        errfile.write("Killing: " + line + "\n")
-        pid = int(line.split()[1])
-        os.kill(pid, 15)
-    return 0

+ 5 - 1
frameworks/Python/flask/setup_nginxuwsgi.py

@@ -1,6 +1,7 @@
-import subprocess
 import multiprocessing
 import multiprocessing
 import os
 import os
+import subprocess
+import time
 
 
 
 
 CWD = os.path.abspath(os.path.dirname(__file__))
 CWD = os.path.abspath(os.path.dirname(__file__))
@@ -19,6 +20,8 @@ def start(args, logfile, errfile):
         subprocess.Popen(
         subprocess.Popen(
             "{0}/uwsgi --ini uwsgi.ini --processes {1} --wsgi app:app".format(bin_dir, NCPU*3),
             "{0}/uwsgi --ini uwsgi.ini --processes {1} --wsgi app:app".format(bin_dir, NCPU*3),
             shell=True, cwd=CWD, stderr=errfile, stdout=logfile)
             shell=True, cwd=CWD, stderr=errfile, stdout=logfile)
+
+        time.sleep(3)
         return 0
         return 0
     except subprocess.CalledProcessError:
     except subprocess.CalledProcessError:
         return 1
         return 1
@@ -31,4 +34,5 @@ def stop(logfile, errfile):
 
 
     subprocess.call(bin_dir + '/uwsgi --stop /tmp/uwsgi.pid',
     subprocess.call(bin_dir + '/uwsgi --stop /tmp/uwsgi.pid',
                     shell=True, stderr=errfile, stdout=logfile)
                     shell=True, stderr=errfile, stdout=logfile)
+    time.sleep(3)
     return 0
     return 0

+ 27 - 0
frameworks/Python/flask/setup_py2.py

@@ -0,0 +1,27 @@
+from __future__ import print_function
+import os
+import subprocess
+import time
+
+CWD = os.path.dirname(__file__)
+
+import multiprocessing
+
+def start(args, logfile, errfile):
+    print("Envoronment variables:")
+    for k, v in os.environ.items():
+        print('%s=%s' % (k, v))
+    print("Cores:", multiprocessing.cpu_count())
+    subprocess.Popen(
+        "$PY2_GUNICORN app:app -c gunicorn_conf.py",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
+    return 0
+
+
+def stop(logfile, errfile):
+    subprocess.call(
+        "kill `cat gunicorn.pid`",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
+    return 0

+ 10 - 20
frameworks/Python/flask/setup_py3.py

@@ -1,31 +1,21 @@
-import subprocess
 import os
 import os
+import subprocess
 import time
 import time
 
 
-proc = None
+CWD = os.path.dirname(__file__)
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
-    global proc
-    proc = subprocess.Popen(
-        "exec $PY3_GUNICORN app:app -c gunicorn_conf.py",
-        cwd="flask", stderr=errfile, stdout=logfile, shell=True)
+    subprocess.Popen(
+        "$PY3_GUNICORN app:app -c gunicorn_conf.py",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
-    global proc
-    if proc is None:
-        return 0
-    proc.terminate()
-    proc = None
-    time.sleep(1)
-
-    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
-    out, err = p.communicate()
-    for line in out.splitlines():
-      if 'gunicorn' in line:
-        errfile.write("Killing: " + line + "\n")
-        pid = int(line.split()[1])
-        os.kill(pid, 15)
+    subprocess.call(
+        "kill `cat gunicorn.pid`",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 10 - 28
frameworks/Python/flask/setup_pypy.py

@@ -1,39 +1,21 @@
-import subprocess
 import os
 import os
+import subprocess
 import time
 import time
 
 
-proc = None
+CWD = os.path.dirname(__file__)
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
-    global proc
-    proc = subprocess.Popen(
-        "exec $PYPY_GUNICORN app:app -c gunicorn_conf.py",
-        cwd="flask", stderr=errfile, stdout=logfile, shell=True)
+    subprocess.Popen(
+        "$PYPY_GUNICORN app:app -c gunicorn_conf.py",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
-    global proc
-    if proc is None:
-        return 0
-    proc.terminate()
-    for _ in range(10):
-        if proc.poll() is not None:
-            break
-        time.sleep(0.2)
-
-    if proc.poll() is None:
-        proc.kill()
-
-    proc = None
-
-    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
-    out, err = p.communicate()
-    for line in out.splitlines():
-      if 'gunicorn' in line:
-        errfile.write("Killing: " + line + "\n")
-        pid = int(line.split()[1])
-        os.kill(pid, 15)
+    subprocess.call(
+        "kill `cat gunicorn.pid`",
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
-

+ 3 - 3
frameworks/Python/pyramid/bash_profile.sh

@@ -1,14 +1,14 @@
-export PY2_ROOT=$IROOT/py2
+export PY2_ROOT=$TROOT/py2
 export PY2=$PY2_ROOT/bin/python
 export PY2=$PY2_ROOT/bin/python
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 
 
-export PYPY_ROOT=$IROOT/pypy
+export PYPY_ROOT=$TROOT/pypy
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 
 
-export PY3_ROOT=$IROOT/py3
+export PY3_ROOT=$TROOT/py3
 export PY3=$PY3_ROOT/bin/python3
 export PY3=$PY3_ROOT/bin/python3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 5 - 0
frameworks/Python/pyramid/gunicorn_conf.py

@@ -1,9 +1,14 @@
 import multiprocessing
 import multiprocessing
+import os
 import sys
 import sys
 
 
 _is_pypy = hasattr(sys, 'pypy_version_info')
 _is_pypy = hasattr(sys, 'pypy_version_info')
+_is_travis = os.environ.get('TRAVIS') == 'true'
 
 
 workers = multiprocessing.cpu_count() * 3
 workers = multiprocessing.cpu_count() * 3
+if _is_travis:
+    workers = 2
+
 bind = "0.0.0.0:8080"
 bind = "0.0.0.0:8080"
 keepalive = 120
 keepalive = 120
 errorlog = '-'
 errorlog = '-'

+ 7 - 4
frameworks/Python/pyramid/install.sh

@@ -1,9 +1,12 @@
 #!/bin/bash
 #!/bin/bash
 
 
-mkdir -p ~/.pip_cache
-export PIP_DOWNLOAD_CACHE=$HOME/.pip_cache
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
 
 
 fw_depends python2 python3
 fw_depends python2 python3
 
 
-$IROOT/py2/bin/pip install -r $TROOT/requirements.txt
-$IROOT/py3/bin/pip3 install -r $TROOT/requirements.txt
+$IROOT/py2/bin/virtualenv $TROOT/py2
+$TROOT/py2/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/py3/bin/python3 -m venv $TROOT/py3
+$TROOT/py3/bin/pip install -r $TROOT/requirements.txt

+ 7 - 4
frameworks/Python/pyramid/setup_py2.py

@@ -1,18 +1,21 @@
-import subprocess
 import os
 import os
+import subprocess
+import time
 
 
-CWD = os.path.abspath(os.path.dirname(__file__))
+CWD = os.path.dirname(__file__)
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PY2_GUNICORN wsgi:app -c gunicorn_conf.py",
         "$PY2_GUNICORN wsgi:app -c gunicorn_conf.py",
-        cwd=CWD, shell=True, stderr=errfile, stdout=logfile)
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
-        cwd=CWD, shell=True, stderr=errfile, stdout=logfile)
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 7 - 4
frameworks/Python/pyramid/setup_py3.py

@@ -1,18 +1,21 @@
-import subprocess
 import os
 import os
+import subprocess
+import time
 
 
-CWD = os.path.abspath(os.path.dirname(__file__))
+CWD = os.path.dirname(__file__)
 
 
 
 
 def start(args, logfile, errfile):
 def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PY3_GUNICORN wsgi:app -c gunicorn_conf.py",
         "$PY3_GUNICORN wsgi:app -c gunicorn_conf.py",
-        cwd=CWD, shell=True, stderr=errfile, stdout=logfile)
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
 def stop(logfile, errfile):
 def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
-        cwd=CWD, shell=True, stderr=errfile, stdout=logfile)
+        cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 8 - 19
frameworks/Python/tornado/README.md

@@ -1,6 +1,6 @@
 # Tornado Benchmarking Test
 # Tornado Benchmarking Test
 
 
-This is the Tornado portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+This is the Tornado portion of a benchmarking test suite comparing a variety of web development platforms.
 
 
 ### JSON Encoding Test
 ### JSON Encoding Test
 
 
@@ -11,25 +11,14 @@ This is the Tornado portion of a [benchmarking test suite](../) comparing a vari
 
 
 * [Database teste source Raw](server.py)
 * [Database teste source Raw](server.py)
 
 
-## Infrastructure Software Versions
-The tests were run with:
-* [Python 2.7.3](http://www.python.org/)
-* [Tornado 3](https://www.tornadoweb.com/)
-* [Mongodb 2.0.4](https://www.mongodb.org/)
 
 
+## Infrastructure Software
 
 
-## Resources
-* http://www.tornadoweb.org/en/stable/documentation.html
-
-## Test URLs
-### JSON Encoding Test
-
-http://localhost:8080/json
+* CPython 2, 3 and PyPy
+* [Tornado](https://www.tornadoweb.com/)
+* [Mongodb](https://www.mongodb.org/) with [motor](http://motor.readthedocs.org/en/stable/)
+* [PostgreSQL](http://www.postgresql.org/) with [momoko](http://momoko.61924.nl/en/latest/)
 
 
-### Data-Store/Database Mapping Test
-
-http://localhost:8080/db
-
-### Variable Query Test
 
 
-http://localhost:8080/db?queries=2
+## Resources
+* http://www.tornadoweb.org/en/stable/documentation.html

+ 3 - 4
frameworks/Python/tornado/bash_profile.sh

@@ -1,15 +1,14 @@
-
-export PY2_ROOT=$IROOT/py2
+export PY2_ROOT=$TROOT/py2
 export PY2=$PY2_ROOT/bin/python
 export PY2=$PY2_ROOT/bin/python
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 
 
-export PYPY_ROOT=$IROOT/pypy
+export PYPY_ROOT=$TROOT/pypy
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 
 
-export PY3_ROOT=$IROOT/py3
+export PY3_ROOT=$TROOT/py3
 export PY3=$PY3_ROOT/bin/python3
 export PY3=$PY3_ROOT/bin/python3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 10 - 4
frameworks/Python/tornado/install.sh

@@ -1,9 +1,15 @@
 #!/bin/bash
 #!/bin/bash
 
 
-mkdir -p ~/.pip_cache
-export PIP_DOWNLOAD_CACHE=$HOME/.pip_cache
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
 
 
 fw_depends python2 python3
 fw_depends python2 python3
 
 
-$IROOT/py2/bin/pip install -r $TROOT/requirements.txt
-$IROOT/py3/bin/pip3 install -r $TROOT/requirements.txt
+$IROOT/py2/bin/virtualenv $TROOT/py2
+$TROOT/py2/bin/pip install -r $TROOT/requirements.txt
+
+$IROOT/py3/bin/python3 -m venv $TROOT/py3
+$TROOT/py3/bin/pip install -r $TROOT/requirements.txt
+
+#$IROOT/pypy/bin/virtualenv $TROOT/pypy
+#$TROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt

+ 0 - 19
frameworks/Python/uwsgi/README.md

@@ -1,19 +0,0 @@
-# WSGI Benchmarking Test
-
-This is the WSGI portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
-
-### JSON Encoding Test
-
-
-* [JSON test controller/view](hello.py)
-
-## Infrastructure Software Versions
-The tests were run with:
-* [Python 2.7.3](http://www.python.org/)
-* [uwsgi 1.9.14](https://uwsgi-docs.readthedocs.org/)
-
-
-## Test URLs
-### JSON Encoding Test
-
-http://localhost:8080/json

+ 3 - 3
frameworks/Python/uwsgi/bash_profile.sh

@@ -1,14 +1,14 @@
-export PY2_ROOT=$IROOT/py2
+export PY2_ROOT=$TROOT/py2
 export PY2=$PY2_ROOT/bin/python
 export PY2=$PY2_ROOT/bin/python
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 
 
-export PYPY_ROOT=$IROOT/pypy
+export PYPY_ROOT=$TROOT/pypy
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 
 
-export PY3_ROOT=$IROOT/py3
+export PY3_ROOT=$TROOT/py3
 export PY3=$PY3_ROOT/bin/python
 export PY3=$PY3_ROOT/bin/python
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 10 - 3
frameworks/Python/uwsgi/install.sh

@@ -1,8 +1,15 @@
 #!/bin/bash
 #!/bin/bash
 
 
-mkdir -p ~/.pip_cache
-export PIP_DOWNLOAD_CACHE=$HOME/.pip_cache
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
 
 
 fw_depends python2 nginx
 fw_depends python2 nginx
 
 
-$IROOT/py2/bin/pip install -r $TROOT/requirements.txt
+$IROOT/py2/bin/virtualenv $TROOT/py2
+$TROOT/py2/bin/pip install -r $TROOT/requirements.txt
+
+#$IROOT/py3/bin/python3 -m venv $TROOT/py3
+#$TROOT/py3/bin/pip install -r $TROOT/requirements.txt
+
+#$IROOT/pypy/bin/virtualenv $TROOT/pypy
+#$TROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt

+ 0 - 2
frameworks/Python/uwsgi/requirements.txt

@@ -1,5 +1,3 @@
-greenlet
-cython
 gevent==1.0.1
 gevent==1.0.1
 uwsgi
 uwsgi
 ujson==1.33
 ujson==1.33

+ 3 - 2
frameworks/Python/uwsgi/setup_nginx.py

@@ -1,6 +1,7 @@
 import subprocess
 import subprocess
 import multiprocessing
 import multiprocessing
 import os
 import os
+import time
 
 
 
 
 CWD = os.path.abspath(os.path.dirname(__file__))
 CWD = os.path.abspath(os.path.dirname(__file__))
@@ -23,6 +24,7 @@ def start(args, logfile, errfile):
             ' --gevent 1000 --wsgi hello',
             ' --gevent 1000 --wsgi hello',
             shell=True, cwd='uwsgi',
             shell=True, cwd='uwsgi',
             stdout=logfile, stderr=errfile)
             stdout=logfile, stderr=errfile)
+        time.sleep(3)
         return 0
         return 0
     except subprocess.CalledProcessError:
     except subprocess.CalledProcessError:
         return 1
         return 1
@@ -36,6 +38,5 @@ def stop(logfile, errfile):
         uwsgi + ' --stop /tmp/uwsgi.pid',
         uwsgi + ' --stop /tmp/uwsgi.pid',
         shell=True, cwd="uwsgi", stderr=errfile, stdout=logfile)
         shell=True, cwd="uwsgi", stderr=errfile, stdout=logfile)
 
 
-    os.system('killall nginx')
-    os.system('killall uwsgi')
+    time.sleep(3)
     return 0
     return 0

+ 3 - 3
frameworks/Python/wsgi/bash_profile.sh

@@ -1,14 +1,14 @@
-export PY2_ROOT=$IROOT/py2
+export PY2_ROOT=$TROOT/py2
 export PY2=$PY2_ROOT/bin/python
 export PY2=$PY2_ROOT/bin/python
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_PIP=$PY2_ROOT/bin/pip
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
 
 
-export PYPY_ROOT=$IROOT/pypy
+export PYPY_ROOT=$TROOT/pypy
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY=$PYPY_ROOT/bin/python
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_PIP=$PYPY_ROOT/bin/pip
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 export PYPY_GUNICORN=$PYPY_ROOT/bin/gunicorn
 
 
-export PY3_ROOT=$IROOT/py3
+export PY3_ROOT=$TROOT/py3
 export PY3=$PY3_ROOT/bin/python
 export PY3=$PY3_ROOT/bin/python
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_PIP=$PY3_ROOT/bin/pip3
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn
 export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 5 - 0
frameworks/Python/wsgi/gunicorn_conf.py

@@ -1,10 +1,15 @@
 import multiprocessing
 import multiprocessing
+import os
 import sys
 import sys
 
 
 _is_pypy = hasattr(sys, 'pypy_version_info')
 _is_pypy = hasattr(sys, 'pypy_version_info')
+_is_travis = os.environ.get('TRAVIS') == 'true'
 
 
 # only implements json and plain. Not wait DB.
 # only implements json and plain. Not wait DB.
 workers = multiprocessing.cpu_count()
 workers = multiprocessing.cpu_count()
+if _is_travis:
+    workers = 2
+
 bind = "0.0.0.0:8080"
 bind = "0.0.0.0:8080"
 keepalive = 120
 keepalive = 120
 errorlog = '-'
 errorlog = '-'

+ 10 - 3
frameworks/Python/wsgi/install.sh

@@ -1,8 +1,15 @@
 #!/bin/bash
 #!/bin/bash
 
 
-mkdir -p ~/.pip_cache
-export PIP_DOWNLOAD_CACHE=$HOME/.pip_cache
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
 
 
 fw_depends python2 nginx
 fw_depends python2 nginx
 
 
-$IROOT/py2/bin/pip install -r $TROOT/requirements.txt
+$IROOT/py2/bin/virtualenv $TROOT/py2
+$TROOT/py2/bin/pip install -r $TROOT/requirements.txt
+
+#$IROOT/py3/bin/python3 -m venv $TROOT/py3
+#$TROOT/py3/bin/pip install -r $TROOT/requirements.txt
+
+#$IROOT/pypy/bin/virtualenv $TROOT/pypy
+#$TROOT/pypy/bin/pip install -r $TROOT/requirements-pypy.txt

+ 4 - 1
frameworks/Python/wsgi/setup.py

@@ -1,5 +1,6 @@
-import subprocess
 import os
 import os
+import subprocess
+import time
 
 
 CWD = os.path.dirname(__file__)
 CWD = os.path.dirname(__file__)
 
 
@@ -8,6 +9,7 @@ def start(args, logfile, errfile):
     subprocess.Popen(
     subprocess.Popen(
         "$PY2_GUNICORN hello:app -c gunicorn_conf.py",
         "$PY2_GUNICORN hello:app -c gunicorn_conf.py",
         cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
         cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0
 
 
 
 
@@ -15,4 +17,5 @@ def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         "kill `cat gunicorn.pid`",
         "kill `cat gunicorn.pid`",
         cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
         cwd=CWD, stderr=errfile, stdout=logfile, shell=True)
+    time.sleep(3)
     return 0
     return 0

+ 3 - 0
frameworks/Python/wsgi/setup_nginxuwsgi.py

@@ -1,6 +1,7 @@
 import subprocess
 import subprocess
 import multiprocessing
 import multiprocessing
 import os
 import os
+import time
 
 
 
 
 CWD = os.path.abspath(os.path.dirname(__file__))
 CWD = os.path.abspath(os.path.dirname(__file__))
@@ -21,6 +22,7 @@ def start(args, logfile, errfile):
             ' --processes ' + str(NCPU) +
             ' --processes ' + str(NCPU) +
             ' --wsgi hello:app',
             ' --wsgi hello:app',
             shell=True, cwd=CWD, stdout=logfile, stderr=errfile)
             shell=True, cwd=CWD, stdout=logfile, stderr=errfile)
+        time.sleep(3)
         return 0
         return 0
     except subprocess.CalledProcessError:
     except subprocess.CalledProcessError:
         return 1
         return 1
@@ -33,4 +35,5 @@ def stop(logfile, errfile):
     subprocess.call(
     subprocess.call(
         bin_dir + '/uwsgi --stop /tmp/uwsgi.pid',
         bin_dir + '/uwsgi --stop /tmp/uwsgi.pid',
         shell=True, cwd=CWD, stderr=errfile, stdout=logfile)
         shell=True, cwd=CWD, stderr=errfile, stdout=logfile)
+    time.sleep(3)
     return 0
     return 0

+ 1 - 0
toolset/setup/linux/languages/pypy.sh

@@ -11,3 +11,4 @@ if [ ! -f "get-pip.py" ]; then
 fw_get https://bootstrap.pypa.io/get-pip.py -O get-pip.py
 fw_get https://bootstrap.pypa.io/get-pip.py -O get-pip.py
 fi
 fi
 ./pypy/bin/pypy get-pip.py
 ./pypy/bin/pypy get-pip.py
+./pypy/bin/pip install virtualenv

+ 1 - 0
toolset/setup/linux/languages/python2.sh

@@ -16,3 +16,4 @@ if [ ! -f "get-pip.py" ]; then
 fw_get https://bootstrap.pypa.io/get-pip.py -O get-pip.py
 fw_get https://bootstrap.pypa.io/get-pip.py -O get-pip.py
 fi
 fi
 ./py2/bin/python get-pip.py
 ./py2/bin/python get-pip.py
+./py2/bin/pip install virtualenv