test(bench): Add Django benchmark (#1087)

* test(bench): Add Django benchmark

* chore: Fix pep8 in django app
This commit is contained in:
Kurt Griffiths 2017-07-20 07:40:23 -06:00 committed by John Vrbanac
parent b51d4e9a35
commit cf011c7c8f
17 changed files with 241 additions and 64 deletions

View File

@ -254,11 +254,12 @@ def run(frameworks, trials, iterations, stat_memory):
def main():
frameworks = [
'bottle',
'django',
'falcon',
'falcon-ext',
'flask',
'pecan',
'werkzeug'
'werkzeug',
]
parser = argparse.ArgumentParser(description='Falcon benchmark runner')
@ -313,7 +314,7 @@ def main():
us_per_req = (sec_per_req * Decimal(10 ** 6))
factor = round_to_int(baseline / sec_per_req)
print('{3}. {0:.<15s}{1:.>06d} req/sec or {2: >3.2f} μs/req ({4}x)'.
print('{3}. {0:.<20s}{1:.>06d} req/sec or {2: >3.2f} μs/req ({4}x)'.
format(name, req_per_sec, us_per_req, i + 1, factor))
if heapy and args.stat_memory:

View File

@ -96,59 +96,26 @@ def werkzeug(body, headers):
return hello
def cherrypy(body, headers):
import cherrypy
# Disable logging
cherrypy.config.update({'environment': 'embedded'})
class HelloResource(object):
exposed = True
def GET(self, account_id, test, limit=8):
user_agent = cherrypy.request.headers['User-Agent'] # NOQA
for name, value in headers.items():
cherrypy.response.headers[name] = value
return body
class Root(object):
pass
root = Root()
root.hello = HelloResource()
conf = {
'/': {
'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
}
}
app = cherrypy.tree.mount(root, '/', conf)
return app
# def wsme(body, headers):
# import wsme
# class HelloService(wsme.WSRoot):
# @wsme.expose(str, str)
# def hello(self, limit='10'):
# import pdb
# pdb.set_trace()
# return body
# ws = HelloService(protocols=['restjson'])
# return ws.wsgiapp()
def pecan(body, headers):
import falcon.bench.nuts.nuts.app as nuts
import pecan
pecan.x_test_body = body
pecan.x_test_headers = headers
import falcon.bench.nuts.nuts.app as nuts
sys.path.append(os.path.dirname(nuts.__file__))
app = nuts.create()
del sys.path[-1]
return app
def django(body, headers):
import django
django.x_test_body = body
django.x_test_headers = headers
from falcon.bench import dj
sys.path.append(os.path.dirname(dj.__file__))
from falcon.bench.dj.dj import wsgi
return wsgi.application

View File

View File

View File

@ -0,0 +1,121 @@
"""
Django settings for dj project.
Generated by 'django-admin startproject' using Django 1.11.3.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 't6gj%z0ee)*xmdoqhm4^er60=s^1g_vs7y!dl2vve4-1u9^+ps'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'hello',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'dj.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'dj.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'

View File

@ -0,0 +1,7 @@
from django.conf.urls import url
from hello import views
urlpatterns = [
url(r'^hello/(?P<account_id>[0-9]+)/test$', views.hello)
]

View File

@ -0,0 +1,16 @@
"""
WSGI config for dj project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dj.settings')
application = get_wsgi_application()

View File

View File

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import AppConfig
class HelloConfig(AppConfig):
name = 'hello'

View File

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# from django.db import models
# Create your models here.

View File

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
# from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,17 @@
import django
from django.http import HttpResponse
_body = django.x_test_body
_headers = django.x_test_headers
def hello(request, account_id):
user_agent = request.META['HTTP_USER_AGENT'] # NOQA
limit = request.GET.get('limit', '10') # NOQA
response = HttpResponse(_body)
for name, value in _headers.items():
response[name] = value
return response

22
falcon/bench/dj/manage.py Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
import os
import sys
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dj.settings')
try:
from django.core.management import execute_from_command_line
except ImportError:
# The above import may fail for some other reason. Ensure that the
# issue is really that Django is missing to avoid masking other
# exceptions on Python 2.
try:
import django # NOQA
except ImportError:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
'available on your PYTHONPATH environment variable? Did you '
'forget to activate a virtual environment?'
)
raise
execute_from_command_line(sys.argv)

View File

@ -1,16 +1,11 @@
import random
import pecan
from pecan import expose, response, request
def rand_string(min, max):
int_gen = random.randint
string_length = int_gen(min, max)
return ''.join([chr(int_gen(ord('\t'), ord('~')))
for i in range(string_length)])
body = rand_string(10240, 10240)
_body = pecan.x_test_body
_headers = pecan.x_test_headers
class TestController(object):
@ -20,10 +15,10 @@ class TestController(object):
@expose(content_type='text/plain')
def test(self):
user_agent = request.headers['User-Agent'] # NOQA
limit = request.params['limit'] # NOQA
response.headers['X-Test'] = 'Funky Chicken'
limit = request.params.get('limit', '10') # NOQA
response.headers.update(_headers)
return body
return _body
class HelloController(object):
@ -36,7 +31,7 @@ class RootController(object):
@expose(content_type='text/plain')
def index(self):
response.headers['X-Test'] = 'Funky Chicken'
return body
response.headers.update(_headers)
return _body
hello = HelloController()

View File

@ -0,0 +1,5 @@
bottle
django
flask
guppy
pecan