app.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. from functools import partial
  2. from operator import attrgetter, itemgetter
  3. from random import randint
  4. from email.utils import formatdate
  5. import os
  6. import sys
  7. from bottle import Bottle, route, request, run, template, response
  8. from bottle.ext import sqlalchemy
  9. from sqlalchemy import create_engine, Column, Integer, Unicode
  10. from sqlalchemy.ext.declarative import declarative_base
  11. try:
  12. import ujson as json
  13. except ImportError:
  14. import json
  15. if sys.version_info[0] == 3:
  16. xrange = range
  17. _is_pypy = hasattr(sys, 'pypy_version_info')
  18. DBDRIVER = 'mysql+pymysql' if _is_pypy else 'mysql'
  19. DBHOSTNAME = 'tfb-database'
  20. DATABASE_URI = '%s://benchmarkdbuser:benchmarkdbpass@%s:3306/hello_world?charset=utf8' % (DBDRIVER, DBHOSTNAME)
  21. app = Bottle()
  22. Base = declarative_base()
  23. db_engine = create_engine(DATABASE_URI)
  24. plugin = sqlalchemy.Plugin(db_engine, keyword='db')
  25. app.install(plugin)
  26. # Engine for raw operation. Use autocommit.
  27. raw_engine = create_engine(DATABASE_URI,
  28. connect_args={'autocommit': True},
  29. pool_reset_on_return=None)
  30. class World(Base):
  31. __tablename__ = "World"
  32. id = Column(Integer, primary_key=True)
  33. randomNumber = Column(Integer)
  34. def serialize(self):
  35. """Return object data in easily serializeable format"""
  36. return {
  37. 'id': self.id,
  38. 'randomNumber': self.randomNumber,
  39. }
  40. class Fortune(Base):
  41. __tablename__ = "Fortune"
  42. id = Column(Integer, primary_key=True)
  43. message = Column(Unicode)
  44. @app.route("/json")
  45. def hello():
  46. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  47. response.content_type = 'application/json'
  48. resp = {"message": "Hello, World!"}
  49. return json.dumps(resp)
  50. @app.route("/db")
  51. def get_random_world_single(db):
  52. """Test Type 2: Single Database Query"""
  53. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  54. wid = randint(1, 10000)
  55. world = db.query(World).get(wid).serialize()
  56. response.content_type = 'application/json'
  57. return json.dumps(world)
  58. @app.route("/raw-db")
  59. def get_random_world_single_raw():
  60. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  61. connection = raw_engine.connect()
  62. wid = randint(1, 10000)
  63. try:
  64. result = connection.execute("SELECT id, randomNumber FROM world WHERE id = " + str(wid)).fetchone()
  65. world = {'id': result[0], 'randomNumber': result[1]}
  66. response.content_type = 'application/json'
  67. return json.dumps(world)
  68. finally:
  69. connection.close()
  70. @app.route("/queries")
  71. def get_random_world(db):
  72. """Test Type 3: Multiple database queries"""
  73. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  74. num_queries = request.query.get('queries', 1, type=int)
  75. if num_queries < 1:
  76. num_queries = 1
  77. if num_queries > 500:
  78. num_queries = 500
  79. rp = partial(randint, 1, 10000)
  80. get = db.query(World).get
  81. worlds = [get(rp()).serialize() for _ in xrange(num_queries)]
  82. response.content_type = 'application/json'
  83. return json.dumps(worlds)
  84. @app.route("/raw-queries")
  85. def get_random_world_raw():
  86. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  87. num_queries = request.query.get('queries', 1, type=int)
  88. if num_queries < 1:
  89. num_queries = 1
  90. if num_queries > 500:
  91. num_queries = 500
  92. worlds = []
  93. rp = partial(randint, 1, 10000)
  94. connection = raw_engine.connect()
  95. try:
  96. for i in xrange(num_queries):
  97. result = connection.execute("SELECT id, randomNumber FROM world WHERE id = " + str(rp())).fetchone()
  98. worlds.append({'id': result[0], 'randomNumber': result[1]})
  99. finally:
  100. connection.close()
  101. response.content_type = 'application/json'
  102. return json.dumps(worlds)
  103. @app.route("/fortune")
  104. def fortune_orm(db):
  105. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  106. fortunes=db.query(Fortune).all()
  107. fortunes.append(Fortune(id=0, message="Additional fortune added at request time."))
  108. fortunes.sort(key=attrgetter('message'))
  109. return template('fortune-obj', fortunes=fortunes)
  110. @app.route("/raw-fortune")
  111. def fortune_raw():
  112. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  113. connection = raw_engine.connect()
  114. try:
  115. fortunes=[(f.id, f.message) for f in connection.execute("SELECT * FROM Fortune")]
  116. fortunes.append((0, u'Additional fortune added at request time.'))
  117. fortunes=sorted(fortunes, key=itemgetter(1))
  118. finally:
  119. connection.close()
  120. return template('fortune', fortunes=fortunes)
  121. @app.route("/updates")
  122. def updates(db):
  123. """Test 5: Database Updates"""
  124. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  125. num_queries = request.query.get('queries', 1, type=int)
  126. if num_queries < 1:
  127. num_queries = 1
  128. if num_queries > 500:
  129. num_queries = 500
  130. worlds = []
  131. rp = partial(randint, 1, 10000)
  132. ids = [rp() for _ in xrange(num_queries)]
  133. ids.sort() # To avoid deadlock
  134. for id in ids:
  135. world = db.query(World).get(id)
  136. world.randomNumber = rp()
  137. worlds.append(world.serialize())
  138. response.content_type = 'application/json'
  139. return json.dumps(worlds)
  140. @app.route("/raw-updates")
  141. def raw_updates():
  142. """Test 5: Database Updates"""
  143. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  144. num_queries = request.query.get('queries', 1, type=int)
  145. if num_queries < 1:
  146. num_queries = 1
  147. if num_queries > 500:
  148. num_queries = 500
  149. conn = raw_engine.connect()
  150. worlds = []
  151. rp = partial(randint, 1, 10000)
  152. for i in xrange(num_queries):
  153. world = conn.execute("SELECT * FROM World WHERE id=%s", (rp(),)).fetchone()
  154. randomNumber = rp()
  155. worlds.append({'id': world['id'], 'randomNumber': randomNumber})
  156. conn.execute("UPDATE World SET randomNumber=%s WHERE id=%s",
  157. (randomNumber, world['id']))
  158. conn.close()
  159. response.content_type = 'application/json'
  160. return json.dumps(worlds)
  161. @app.route('/plaintext')
  162. def plaintext():
  163. """Test 6: Plaintext"""
  164. response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)
  165. response.content_type = 'text/plain'
  166. return b'Hello, World!'
  167. if __name__ == "__main__":
  168. app.run(host='0.0.0.0', debug=False)