Browse Source

Merge branch 'uwsgi_perf' of https://github.com/MalcolmEvershed/FrameworkBenchmarks into pr479_MalcomEvershed_uwsgi_wsgi_bottle_flask_20131003-1
Relates to pull request 479. https://github.com/TechEmpower/FrameworkBenchmarks/pull/479

[email protected] 12 years ago
parent
commit
8fb77456fb

+ 23 - 0
bottle/benchmark_config

@@ -90,6 +90,29 @@
       "display_name": "bottle-raw",
       "display_name": "bottle-raw",
       "notes": "",
       "notes": "",
       "versus": "wsgi"
       "versus": "wsgi"
+    },
+    "nginx-uwsgi": {
+      "setup_file": "setup_nginxuwsgi",
+      "json_url": "/json",
+      "db_url": "/dbs",
+      "query_url": "/db?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "bottle",
+      "language": "Python",
+      "orm": "Full",
+      "platform": "wsgi",
+      "webserver": "nginx-uWSGI",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "bottle-nginx-uWSGI",
+      "notes": "",
+      "versus": "wsgi"
     }
     }
   }]
   }]
 }
 }

+ 27 - 0
bottle/setup_nginxuwsgi.py

@@ -0,0 +1,27 @@
+import subprocess
+import multiprocessing
+import os
+import setup_util
+
+bin_dir = os.path.expanduser('~/FrameworkBenchmarks/installs/py2/bin')
+config_dir = os.path.expanduser('~/FrameworkBenchmarks/config')
+NCPU = multiprocessing.cpu_count()
+
+def start(args):
+    setup_util.replace_text("bottle/app.py", "DBHOSTNAME", args.database_host)
+    try:
+        subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' +
+            config_dir + '/nginx_uwsgi.conf', shell=True)
+        # Run in the background, but keep stdout/stderr for easy debugging
+        subprocess.Popen(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi.ini' +
+            ' --processes ' + str(NCPU * 3) +
+            ' --wsgi app:app',
+            shell=True, cwd='bottle')
+        return 0
+    except subprocess.CalledProcessError:
+        return 1
+
+def stop():
+    subprocess.call('sudo /usr/local/nginx/sbin/nginx -s stop', shell=True)
+    subprocess.call(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi_stop.ini', shell=True)
+    return 0

+ 45 - 0
config/nginx_uwsgi.conf

@@ -0,0 +1,45 @@
+# This file is based on /usr/local/nginx/conf/nginx.conf.default.
+
+# One worker process per core
+worker_processes auto;
+
+events {
+    # This may need to be increased for the high-concurrency plaintext test.
+    worker_connections  1024;
+}
+
+http {
+    include       /usr/local/nginx/conf/mime.types;
+    default_type  application/octet-stream;
+
+    # turn off request logging for performance
+    access_log off;
+
+    # I think these only options affect static file serving
+    sendfile        on;
+    tcp_nopush      on;
+
+    # Allow many HTTP Keep-Alive requests in a single TCP connection before
+    # closing it (the default is 100). This will minimize the total number
+    # of TCP connections opened/closed. The problem is that this may cause
+    # some worker processes to be handling too connections relative to the
+    # other workers based on an initial imbalance, so this is disabled for
+    # now.
+#    keepalive_requests 1000;
+
+    #keepalive_timeout  0;
+    keepalive_timeout  65;
+
+    server {
+        # For information on deferred, see:
+        # http://nginx.org/en/docs/http/ngx_http_core_module.html#listen
+        # http://www.techrepublic.com/article/take-advantage-of-tcp-ip-options-to-optimize-data-transmission/
+        listen       8080 default_server deferred;
+        server_name  localhost;
+
+        location / {
+            uwsgi_pass unix:/tmp/uwsgi.sock;
+            include /usr/local/nginx/conf/uwsgi_params;
+        }
+    }    
+}

+ 18 - 0
config/uwsgi.ini

@@ -0,0 +1,18 @@
+[uwsgi]
+master
+; increase listen queue used for nginx connecting to uWSGI
+listen = 5000
+; for performance
+disable-logging
+; use UNIX sockets instead of TCP loopback for performance
+socket = /tmp/uwsgi.sock
+; allow nginx to access the UNIX socket
+chmod-socket = 666
+; Avoid thundering herd problem http://uwsgi-docs.readthedocs.org/en/latest/articles/SerializingAccept.html .
+; This is currently disabled because when I tried it with flask, it caused a
+; 20% performance hit. The CPU cores could not be saturated with thunder-lock.
+; I'm not yet sure the full story, so this is presently disabled. Also,
+; disabling this caused bottle to get ~13% faster.
+;thunder-lock
+; used by uwsgi_stop.ini
+pidfile = /tmp/uwsgi.pid

+ 4 - 0
config/uwsgi_stop.ini

@@ -0,0 +1,4 @@
+# If uWSGI was started with --ini uwsgi.ini, it can be stopped with --ini uwsgi_stop.ini
+
+[uwsgi]
+stop = /tmp/uwsgi.pid

+ 23 - 0
flask/benchmark_config

@@ -111,6 +111,29 @@
       "display_name": "flask-pypy",
       "display_name": "flask-pypy",
       "notes": "",
       "notes": "",
       "versus": "wsgi"
       "versus": "wsgi"
+    },
+    "nginx-uwsgi": {
+      "setup_file": "setup_nginxuwsgi",
+      "json_url": "/json",
+      "db_url": "/dbs",
+      "query_url": "/db?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "flask",
+      "language": "Python",
+      "orm": "Full",
+      "platform": "wsgi",
+      "webserver": "nginx-uWSGI",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "flask-nginx-uWSGI",
+      "notes": "",
+      "versus": "wsgi"
     }
     }
   }]
   }]
 }
 }

+ 27 - 0
flask/setup_nginxuwsgi.py

@@ -0,0 +1,27 @@
+import subprocess
+import multiprocessing
+import os
+import setup_util
+
+bin_dir = os.path.expanduser('~/FrameworkBenchmarks/installs/py2/bin')
+config_dir = os.path.expanduser('~/FrameworkBenchmarks/config')
+NCPU = multiprocessing.cpu_count()
+
+def start(args):
+    setup_util.replace_text("flask/app.py", "DBHOSTNAME", args.database_host)
+    try:
+        subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' +
+            config_dir + '/nginx_uwsgi.conf', shell=True)
+        # Run in the background, but keep stdout/stderr for easy debugging
+        subprocess.Popen(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi.ini' +
+            ' --processes ' + str(NCPU * 3) +
+            ' --wsgi app:app',
+            shell=True, cwd='flask')
+        return 0
+    except subprocess.CalledProcessError:
+        return 1
+
+def stop():
+    subprocess.call('sudo /usr/local/nginx/sbin/nginx -s stop', shell=True)
+    subprocess.call(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi_stop.ini', shell=True)
+    return 0

+ 20 - 2
uwsgi/benchmark_config

@@ -8,16 +8,34 @@
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Platform",
       "classification": "Platform",
       "database": "None",
       "database": "None",
-      "framework": "uwsgi",
+      "framework": "wsgi",
       "language": "Python",
       "language": "Python",
       "orm": "Raw",
       "orm": "Raw",
       "platform": "wsgi",
       "platform": "wsgi",
-      "webserver": "uwsgi",
+      "webserver": "uWSGI",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
       "display_name": "uwsgi",
       "display_name": "uwsgi",
       "notes": "",
       "notes": "",
       "versus": ""
       "versus": ""
+    },
+    "nginx-uwsgi": {
+      "setup_file": "setup_nginx",
+      "json_url": "/json",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "wsgi",
+      "language": "Python",
+      "orm": "Raw",
+      "platform": "wsgi",
+      "webserver": "nginx-uWSGI",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "uwsgi-nginx-uWSGI",
+      "notes": "",
+      "versus": ""
     }
     }
   }]
   }]
 }
 }

+ 1 - 1
uwsgi/hello.py

@@ -7,7 +7,7 @@ def application(environ, start_response):
     }
     }
     data = ujson.dumps(response)
     data = ujson.dumps(response)
     response_headers = [
     response_headers = [
-        ('Content-type', 'text/plain'),
+        ('Content-type', 'application/json'),
         ('Content-Length', str(len(data)))
         ('Content-Length', str(len(data)))
     ]
     ]
     start_response('200 OK', response_headers)
     start_response('200 OK', response_headers)

+ 7 - 2
uwsgi/setup.py

@@ -9,9 +9,14 @@ uwsgi = os.path.expanduser('~/FrameworkBenchmarks/installs/py2/bin/uwsgi')
 PROCS = multiprocessing.cpu_count()
 PROCS = multiprocessing.cpu_count()
 
 
 def start(args):
 def start(args):
+    # --http and --http-processes create http router processes that process the
+    # incoming connections and pass them to the worker processes (-p). We use
+    # PROCS number of http router processes so that a single router process
+    # doesn't become a bottleneck.
     subprocess.Popen(
     subprocess.Popen(
-        uwsgi + ' --master -L --gevent 1000 --http :8080 --http-keepalive ' +
-        '-p ' + str(PROCS) + ' -w hello --add-header "Connection: keep-alive" ' +
+        uwsgi + ' --master -L -l 5000 --gevent 1000 --http :8080 --http-keepalive ' +
+        ' --http-processes ' + str(PROCS) + ' -p ' + str(PROCS) + ' -w hello ' +
+        ' --add-header "Connection: keep-alive" ' +
         ' --pidfile /tmp/uwsgi.pid',
         ' --pidfile /tmp/uwsgi.pid',
         shell=True, cwd="uwsgi")
         shell=True, cwd="uwsgi")
     return 0
     return 0

+ 26 - 0
uwsgi/setup_nginx.py

@@ -0,0 +1,26 @@
+import subprocess
+import multiprocessing
+import os
+
+bin_dir = os.path.expanduser('~/FrameworkBenchmarks/installs/py2/bin')
+config_dir = os.path.expanduser('~/FrameworkBenchmarks/config')
+NCPU = multiprocessing.cpu_count()
+
+def start(args):
+    try:
+        subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' +
+            config_dir + '/nginx_uwsgi.conf', shell=True)
+        # Run in the background, but keep stdout/stderr for easy debugging.
+        # Note that this uses --gevent 1000 just like setup.py.
+        subprocess.Popen(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi.ini' +
+            ' --processes ' + str(NCPU) +
+            ' --gevent 1000 --wsgi hello',
+            shell=True, cwd='uwsgi')
+        return 0
+    except subprocess.CalledProcessError:
+        return 1
+
+def stop():
+    subprocess.call('sudo /usr/local/nginx/sbin/nginx -s stop', shell=True)
+    subprocess.call(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi_stop.ini', shell=True)
+    return 0

+ 19 - 0
wsgi/benchmark_config

@@ -19,6 +19,25 @@
       "display_name": "wsgi",
       "display_name": "wsgi",
       "notes": "",
       "notes": "",
       "versus": "wsgi"
       "versus": "wsgi"
+    },
+    "nginx-uwsgi": {
+      "setup_file": "setup_nginxuwsgi",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "wsgi",
+      "language": "Python",
+      "orm": "Raw",
+      "platform": "wsgi",
+      "webserver": "nginx-uWSGI",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "wsgi-nginx-uWSGI",
+      "notes": "",
+      "versus": "wsgi"
     }
     }
   }]
   }]
 }
 }

+ 25 - 0
wsgi/setup_nginxuwsgi.py

@@ -0,0 +1,25 @@
+import subprocess
+import multiprocessing
+import os
+
+bin_dir = os.path.expanduser('~/FrameworkBenchmarks/installs/py2/bin')
+config_dir = os.path.expanduser('~/FrameworkBenchmarks/config')
+NCPU = multiprocessing.cpu_count()
+
+def start(args):
+    try:
+        subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' +
+            config_dir + '/nginx_uwsgi.conf', shell=True)
+        # Run in the background, but keep stdout/stderr for easy debugging
+        subprocess.Popen(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi.ini' +
+            ' --processes ' + str(NCPU) +
+            ' --wsgi hello:app',
+            shell=True, cwd='wsgi')
+        return 0
+    except subprocess.CalledProcessError:
+        return 1
+
+def stop():
+    subprocess.call('sudo /usr/local/nginx/sbin/nginx -s stop', shell=True)
+    subprocess.call(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi_stop.ini', shell=True)
+    return 0