app.py 5.5 KB

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