Browse Source

Merge branch 'wheezyweb' of https://github.com/TechEmpower/FrameworkBenchmarks into wheezyweb

Keith Newman 10 years ago
parent
commit
3e514cbf16

+ 1 - 0
.travis.yml

@@ -123,6 +123,7 @@ env:
     - "TESTDIR=Python/pyramid"
     - "TESTDIR=Python/tornado"
     - "TESTDIR=Python/uwsgi"
+    - "TESTDIR=Python/wheezyweb"
     - "TESTDIR=Python/wsgi"
     - "TESTDIR=Racket/racket-ws"
     - "TESTDIR=Ruby/grape"

+ 41 - 0
frameworks/Python/wheezyweb/README.md

@@ -0,0 +1,41 @@
+# wheezy.web Benchmark Test 
+
+Single file test, [app.py](app.py)
+
+## Description
+
+wheezy.web WSGI web framework (https://pythonhosted.org/wheezy.web/)
+
+### Database
+
+(none at the moment)
+
+### Server
+
+* wheezy.web
+
+## Test URLs
+### JSON Encoding
+
+http://localhost:8080/json
+
+### Plaintext
+
+http://localhost:8080/plaintext
+
+### DB
+
+http://localhost:8080/db
+
+
+### Query
+
+http://localhost:8080/queries?queries=2
+
+### Update
+
+http://localhost:8080/updates?queries=2
+
+### Fortune
+
+http://localhost:8080/fortune

+ 150 - 0
frameworks/Python/wheezyweb/app.py

@@ -0,0 +1,150 @@
+import os
+import sys
+from functools import partial
+from operator import attrgetter
+from random import randint
+
+import bleach
+
+from wheezy.http import HTTPResponse
+from wheezy.http import WSGIApplication
+from wheezy.routing import url
+from wheezy.web.handlers import BaseHandler
+from wheezy.web.middleware import bootstrap_defaults
+from wheezy.web.middleware import path_routing_middleware_factory
+
+from wheezy.template.engine import Engine
+from wheezy.template.ext.core import CoreExtension
+from wheezy.template.loader import FileLoader
+
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import create_engine, Column
+from sqlalchemy.types import String, Integer, Unicode
+from sqlalchemy.orm import sessionmaker
+
+from meinheld import server
+
+DBDRIVER = 'mysql'
+DBHOSTNAME = os.environ.get('DBHOST', 'localhost')
+DATABASE_URI = '%s://benchmarkdbuser:benchmarkdbpass@%s:3306/hello_world?charset=utf8' % (DBDRIVER, DBHOSTNAME)
+
+Base = declarative_base()
+db_engine = create_engine(DATABASE_URI)
+Session = sessionmaker(bind=db_engine)
+db_session = Session()
+
+if sys.version_info[0] == 3:
+    xrange = range
+
+def getQueryNum(queryString):
+    try:
+        int(queryString)
+        return int(queryString)
+    except ValueError:
+        return 1
+
+class Fortune(Base):
+    __tablename__ = "Fortune"
+    id = Column(Integer, primary_key=True)
+    message = Column(String)
+
+    def serialize(self):
+        return {
+            'id': self.id,
+            'randomNumber': self.randomNumber,
+        }
+
+class World(Base):
+    __tablename__ = "World"
+    id = Column(Integer, primary_key=True)
+    randomNumber = Column(Integer)
+    def serialize(self):
+        return {
+            'id': self.id,
+            'randomNumber': self.randomNumber,
+        }
+
+class JsonHandler(BaseHandler):
+    def get(self):
+        return self.json_response({"message": "Hello, world!"})
+
+class DbHandler(BaseHandler):
+    def get(self):
+        db_engine.connect()
+        wid = randint(1, 10000)
+        world = db_session.query(World).get(wid).serialize()
+        return self.json_response(world)
+
+class QueriesHandler(BaseHandler):
+    def get(self):
+        queries = self.request.get_param("queries")
+        num_queries = getQueryNum(queries)
+        if num_queries < 1:
+            num_queries = 1
+        if num_queries > 500:
+            num_queries = 500
+        rp = partial(randint, 1, 10000)
+        get = db_session.query(World).get
+        worlds = [get(rp()).serialize() for _ in xrange(num_queries)]
+        return self.json_response(worlds)
+
+class UpdatesHandler(BaseHandler):
+    def get(self):
+        queries = self.request.get_param("queries")
+        num_queries = getQueryNum(queries)
+        if num_queries < 1:
+            num_queries = 1
+        if num_queries > 500:
+            num_queries = 500
+        worlds = []
+        rp = partial(randint, 1, 10000)
+        ids = [rp() for _ in xrange(num_queries)]
+        ids.sort() # To avoid deadlock
+        for id in ids:
+            world = db_session.query(World).get(id)
+            world.randomNumber = rp()
+            worlds.append(world.serialize())
+        return self.json_response(worlds)
+
+class FortuneHandler(BaseHandler):
+    def get(self):
+        fortunes = db_session.query(Fortune).all()
+        fortunes.append(Fortune(id=0, message="Additional fortune added at request time."))
+        fortunes.sort(key=attrgetter("message"))
+        engine = Engine(loader=FileLoader(["views"]), extensions=[CoreExtension()])
+        template = engine.get_template("fortune.html")
+        for f in fortunes:
+            f.message = bleach.clean(f.message)
+        template_html = template.render({"fortunes": fortunes})		
+
+        response = HTTPResponse()
+        response.write(template_html)
+        return response
+
+def plaintext(request):
+    response = HTTPResponse()
+    response.write("Hello, world!")
+    return response
+
+all_urls = [
+    url("plaintext", plaintext, name="plaintext"),
+    url("json", JsonHandler, name="json"),
+    url("db", DbHandler, name="db"),
+    url("queries", QueriesHandler, name="queries"),
+    url("updates", UpdatesHandler, name="updates"),
+    url("fortune", FortuneHandler, name="fortune")
+]
+
+options = {}
+
+app = WSGIApplication(
+    middleware = [
+        bootstrap_defaults(url_mapping=all_urls),
+        path_routing_middleware_factory
+    ],
+    options = options
+)
+
+if __name__ == '__main__':
+    server.listen(("127.0.0.1", 8080))
+    server.run(app)

+ 9 - 0
frameworks/Python/wheezyweb/bash_profile.sh

@@ -0,0 +1,9 @@
+export PY2_ROOT=$IROOT/py2
+export PY2=$PY2_ROOT/bin/python
+export PY2_PIP=$PY2_ROOT/bin/pip
+export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
+
+export PY3_ROOT=$IROOT/py3
+export PY3=$PY3_ROOT/bin/python3
+export PY3_PIP=$PY3_ROOT/bin/pip3
+export PY3_GUNICORN=$PY3_ROOT/bin/gunicorn

+ 49 - 0
frameworks/Python/wheezyweb/benchmark_config

@@ -0,0 +1,49 @@
+{
+  "framework": "wheezyweb",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "wheezy.web",
+      "language": "Python",
+      "orm": "Full",
+      "platform": "Meinheld",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "wheezy.web",
+      "notes": "CPython 2.7"
+    },
+    "py3": {
+      "setup_file": "setup_py3",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "wheezy.web",
+      "language": "Python",
+      "orm": "Full",
+      "platform": "Meinheld",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "wheezy.web-py3",
+      "notes": "CPython 3.4"
+    }
+  }]
+}

+ 25 - 0
frameworks/Python/wheezyweb/gunicorn_conf.py

@@ -0,0 +1,25 @@
+import multiprocessing
+import os
+import sys
+
+_is_pypy = hasattr(sys, 'pypy_version_info')
+_is_travis = os.environ.get('TRAVIS') == 'true'
+
+workers = multiprocessing.cpu_count() * 3
+if _is_travis:
+    workers = 2
+
+bind = "0.0.0.0:8080"
+keepalive = 120
+errorlog = '-'
+pidfile = 'gunicorn.pid'
+
+if _is_pypy:
+    worker_class = "tornado"
+else:
+    worker_class = "meinheld.gmeinheld.MeinheldWorker"
+
+    def post_fork(server, worker):
+        # Disalbe access log
+        import meinheld.server
+        meinheld.server.set_access_logger(None)

+ 11 - 0
frameworks/Python/wheezyweb/install.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
+
+fw_depends python2 python3 
+
+$PY2_PIP install --install-option="--prefix=${PY2_ROOT}" -r $TROOT/requirements.txt
+
+$PY3_PIP install --install-option="--prefix=${PY3_ROOT}" -r $TROOT/requirements.txt
+

+ 12 - 0
frameworks/Python/wheezyweb/requirements.txt

@@ -0,0 +1,12 @@
+wheezy.web==0.1.469
+wheezy.template==0.1.159
+
+bleach==1.4.1
+
+SQLAlchemy==0.9.9
+mysqlclient==1.3.6
+
+gunicorn==19.3.0
+meinheld==0.5.7
+
+greenlet==0.4.5

+ 3 - 0
frameworks/Python/wheezyweb/setup.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+$PY2_GUNICORN app:app -c gunicorn_conf.py &

+ 3 - 0
frameworks/Python/wheezyweb/setup_py3.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+$PY3_GUNICORN app:app -c gunicorn_conf.py &

+ 22 - 0
frameworks/Python/wheezyweb/views/fortune.html

@@ -0,0 +1,22 @@
+@require(fortunes)
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+@for fortune in fortunes:
+<tr>
+<td>@str(fortune.id)</td>
+<td>@fortune.message</td>
+</tr>
+@end
+</table>
+</body>
+</html>
+