| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 | #!/usr/bin/env pythonimport osimport sysimport multiprocessingimport itertoolsfrom collections import namedtuplefrom operator import attrgetter, itemgetterimport randomfrom email.utils import formatdateimport flaskfrom pony import ormif sys.version_info[0] == 3:    xrange = range    _is_pypy = hasattr(sys, "pypy_version_info")if _is_pypy:    import psycopg2cffi.compat    psycopg2cffi.compat.register()_is_travis = os.environ.get('TRAVIS') == 'true'_is_gunicorn = "gunicorn" in os.environ.get("SERVER_SOFTWARE", "")_cpu_count = multiprocessing.cpu_count()if _is_travis:    _cpu_count = 2_raw = os.getenv('USE_RAW', "0") == "1"_use_orjson = os.getenv('USE_ORJSON', "0") == "1"if _use_orjson:    import orjson as json_use_ujson = os.getenv('USE_UJSON', "0") == "1"if _use_ujson:    import ujson as json    if not _use_orjson and not _use_ujson:    import json    from flask import jsonifyDBDRV  = "postgres"DBHOST = "tfb-database"DBUSER = "benchmarkdbuser"DBPSWD = "benchmarkdbpass"# setupapp = flask.Flask(__name__)app.config["JSONIFY_PRETTYPRINT_REGULAR"] = False# -----------------------------------------------------------------------------response_server = Noneresponse_add_date = False@app.after_requestdef after_request(response):    if response_server:        response.headers['Server'] = response_server    if response_add_date:        response.headers['Date'] = formatdate(timeval=None, localtime=False, usegmt=True)    return responseif _use_orjson or _use_ujson:    def jsonify(jdict):        return json.dumps(jdict), { "Content-Type": "application/json" }# -----------------------------------------------------------------------------def get_num_queries():    try:        num_queries = flask.request.args.get("queries", 1, type=int)    except ValueError:        num_queries = 1    if num_queries < 1:        return 1    if num_queries > 500:        return 500    return num_queriesdef generate_ids(num_queries):    return random.sample(range(1, 10001), num_queries)if _raw:    import jinja2        if _is_pypy:        from psycopg2cffi.pool import ThreadedConnectionPool        from psycopg2cffi.extras import execute_batch    else:        from psycopg2.pool import ThreadedConnectionPool        from psycopg2.extras import execute_batch    pool_size = int(_cpu_count * 2.5 / 4)    if _is_travis:        pool_size = 5        POOL = ThreadedConnectionPool(        minconn=pool_size,        maxconn=pool_size,        database="hello_world",        user=DBUSER,        password=DBPSWD,        host=DBHOST,        port=5432,    )    read_row_sql = (        'SELECT world."randomnumber", world."id" FROM "world" WHERE id = %(id)s'    )    prepared_read_row_sql = (        'SELECT world."randomnumber", world."id" FROM "world" WHERE id = $1'    )    write_row_sql = 'UPDATE "world" SET "randomnumber"=$1 WHERE id=$2'    ADDITIONAL_ROW = (0, "Additional fortune added at request time.")    db = POOL.getconn()    cursor = db.cursor()    cursor.execute("PREPARE read_stmt (int) AS " + prepared_read_row_sql)    cursor.execute("PREPARE write_stmt (int, int) AS " + write_row_sql)    cursor.execute('PREPARE fortune AS SELECT * FROM "Fortune"')    del cursor    POOL.putconn(db)    del db    def db_query(arg):        (cursor, ident) = arg        cursor.execute("EXECUTE read_stmt(%s)", [ident])        result = cursor.fetchone()        return result            fn = os.path.join("templates", "fortune_raw.html")    with open(fn, "r") as template_file:        template_text = template_file.read()    FORTUNE_TEMPLATE = jinja2.Template(template_text)    #Fortune = namedtuple("Fortune", ["id", "message"])else: # --------- PonyORM ------------------------------------------------    app.config["STORM_DATABASE_URI"] = "{}://{}:{}@{}:5432/hello_world".format(DBDRV, DBUSER, DBPSWD, DBHOST)        db = orm.Database()    db.bind(DBDRV, host=DBHOST, port=5432, user=DBUSER, password=DBPSWD, database="hello_world")    class World(db.Entity):        _table_ = "world"        id = orm.PrimaryKey(int)        randomNumber = orm.Required(int, column="randomnumber")        def to_dict(self):            """Return object data in easily serializeable format"""            return {"id": self.id, "randomNumber": self.randomNumber}    class Fortune(db.Entity):        _table_ = "fortune"        id = orm.PrimaryKey(int, auto=True)        message = orm.Required(str)    db.generate_mapping(create_tables=False)    # ----------------------------------------------------------------------------------------@app.route("/json")def json_data():    return flask.jsonify(message="Hello, World!")@app.route("/json-raw")def json_data_raw():    return jsonify( {"message": "Hello, World!"} )@app.route("/db")def get_random_world_single():    wid = random.randint(1, 10000)    with orm.db_session(serializable=False):        world = World[wid]    return jsonify(world.to_dict())@app.route("/db-raw")def get_random_world_single_raw():    db = POOL.getconn()    cursor = db.cursor()    cursor.execute("EXECUTE read_stmt(%s)", generate_ids(1))    result = cursor.fetchone()    world = {"id": result[0], "randomNumber": result[1]}    POOL.putconn(db)    return jsonify(world)@app.route("/query")def get_random_world():    with orm.db_session(serializable=False):        worlds = [World[ident].to_dict() for ident in generate_ids(get_num_queries())]    return jsonify(worlds)@app.route("/query-raw")def get_random_world_raw():    db = POOL.getconn()    cursor = db.cursor()    num_queries = get_num_queries()    results = map(db_query, zip(itertools.repeat(cursor, num_queries), generate_ids(num_queries)))    worlds = [ {"id": result[0], "randomNumber": result[1]} for result in results ]    POOL.putconn(db)    return jsonify(worlds)@app.route("/fortunes")def get_fortunes():    with orm.db_session(serializable=False):        fortunes = list(orm.select(fortune for fortune in Fortune))    tmp_fortune = namedtuple("Fortune", ["id", "message"])    fortunes.append(        tmp_fortune(id=0, message="Additional fortune added at request time.")    )    fortunes.sort(key=attrgetter("message"))    return flask.render_template("fortunes.html", fortunes=fortunes)@app.route("/fortunes-raw")def get_fortunes_raw():    db = POOL.getconn()    cursor = db.cursor()    cursor.execute("EXECUTE fortune")    fortunes = list(cursor.fetchall())    fortunes.append(ADDITIONAL_ROW)    fortunes.sort(key=itemgetter(1))    POOL.putconn(db)    return flask.Response(FORTUNE_TEMPLATE.render(fortunes=fortunes))@app.route("/updates")def updates():    num_queries = get_num_queries()    ids = generate_ids(num_queries)    ids.sort()    worlds = []    with orm.db_session(serializable=False):        for ident in ids:            world = World[ident]            world.randomNumber = random.randint(1, 10000)            worlds.append({"id": world.id, "randomNumber": world.randomNumber})    return jsonify(worlds)@app.route("/updates-raw")def updates_raw():    db = POOL.getconn()    cursor = db.cursor()    num_queries = get_num_queries()    ids = generate_ids(num_queries)    update_values = generate_ids(num_queries)    list(map(db_query, zip(itertools.repeat(cursor, num_queries), generate_ids(num_queries))))    worlds = list(zip(ids, update_values))    execute_batch(cursor, "EXECUTE write_stmt(%s, %s)", worlds)    db.commit()    POOL.putconn(db)    data = [ {"id": ident, "randomNumber": update} for ident, update in worlds ]    return jsonify(data)@app.route("/plaintext")def plaintext():    response = flask.make_response(b"Hello, World!")    response.content_type = "text/plain"    return response# -----------------------------------------------------------------------------------if __name__ == "__main__":    import optparse    import logging    import signal    import re    parser = optparse.OptionParser("usage: %prog [options]", add_help_option=False)    parser.add_option("-h", "--host", dest="host", default='0.0.0.0', type="string")    parser.add_option("-p", "--port", dest="port", default=8080, type="int")    parser.add_option("-s", "--server", dest="server", default="gunicorn", type="string")    parser.add_option("-w", "--workers", dest="workers", default=0, type="int")    parser.add_option("-k", "--keepalive", dest="keepalive", default=60, type="int")    parser.add_option("-v", "--verbose", dest="verbose", default=0, type="int")    (opt, args) = parser.parse_args()     workers = opt.workers if opt.workers > 0 else _cpu_count    if _is_travis:        workers = 2    worker_list = [ ]    def run_app():        global response_server        global response_add_date                if opt.server == "werkzeug":            import werkzeug            werkzeug.serving.WSGIRequestHandler.protocol_version = "HTTP/1.1"            wzlog = logging.getLogger("werkzeug")            wzlog.setLevel(logging.WARN)            use_reloader = False # True = Use a reloader process to restart the server process when files are changed            response_server = None            response_add_date = False            werkzeug.serving.run_simple(opt.host, opt.port, app, use_reloader=use_reloader)         if opt.server == 'fastwsgi':            import fastwsgi            response_server = "FastWSGI"            response_add_date = False            fastwsgi.server.backlog = 4096            fastwsgi.run(app, host=opt.host, port=opt.port, loglevel=opt.verbose)        if opt.server == 'socketify':            import socketify            response_server = None            response_add_date = False            msg = "Listening on http://0.0.0.0:{port} now\n".format(port=opt.port)            socketify.WSGI(app).listen(opt.port, lambda config: logging.info(msg)).run()    def create_fork():        pid = os.fork()        if pid > 0:                        return pid        try:            run_app()        except KeyboardInterrupt:            pass        sys.exit(0)    for i in range(0, workers):        pid = create_fork()        print("Worker process added with PID:", pid)        worker_list.append(pid)    print("Running {} workers".format(len(worker_list)))    try:        for i in range(workers):            os.wait()    except KeyboardInterrupt:        print("\n" + "Stopping all workers")        for pid in worker_list:            os.kill(pid, signal.SIGINT)
 |