Mercurial > p > roundup > code
comparison test/benchmark.py @ 7876:7a3392f1f7ac
test: update benchmark add basic CLI support for backend arguments
Also docstring for file.
Handle ^C interruption and cleanup partly created databases.
Support postgresql and mysql.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Tue, 16 Apr 2024 22:19:29 -0400 |
| parents | 867418c24339 |
| children | 9c3ec0a5c7fc |
comparison
equal
deleted
inserted
replaced
| 7875:d4f6ba8e3c1e | 7876:7a3392f1f7ac |
|---|---|
| 1 """ Usage: python benchmark.py ["database backend list" | backend1] [backend2] | |
| 2 | |
| 3 Import the backend (anydbm, sqlite by default) and run some performance | |
| 4 tests. Example: | |
| 5 | |
| 6 test default anypy and sqlite backends | |
| 7 | |
| 8 python benchmark.py | |
| 9 | |
| 10 test mysql and sqlite backends | |
| 11 | |
| 12 python benchmark.py mysql sqlite | |
| 13 | |
| 14 or | |
| 15 | |
| 16 python benchmark.py "mysql sqlite" | |
| 17 | |
| 18 test all backends | |
| 19 | |
| 20 python benchmark.py anydbm mysql postgresql sqlite | |
| 21 | |
| 22 | |
| 23 """ | |
| 1 from __future__ import print_function | 24 from __future__ import print_function |
| 2 import sys, os, time | 25 import sys, os, time |
| 3 import importlib, signal, shutil | 26 import importlib, signal, shutil |
| 4 | 27 |
| 5 # --- patch sys.path to make sure 'import roundup' finds correct version | 28 # --- patch sys.path to make sure 'import roundup' finds correct version |
| 15 Interval, DatabaseError, Boolean, Number | 38 Interval, DatabaseError, Boolean, Number |
| 16 from roundup import date, password | 39 from roundup import date, password |
| 17 | 40 |
| 18 from test.db_test_base import config | 41 from test.db_test_base import config |
| 19 | 42 |
| 43 # global for the default signal hander so | |
| 44 # my signal handler can reset before it raises signal. | |
| 20 int_sig_default_handler = None | 45 int_sig_default_handler = None |
| 21 | 46 |
| 22 def setupSchema(db, module): | 47 def setupSchema(db, module): |
| 23 status = module.Class(db, "status", name=String()) | 48 status = module.Class(db, "status", name=String()) |
| 24 status.setkey("name") | 49 status.setkey("name") |
| 36 db.commit() | 61 db.commit() |
| 37 | 62 |
| 38 def rm_db_on_signal(sig, frame): | 63 def rm_db_on_signal(sig, frame): |
| 39 print("removing incomplete database %s due to interruption." % | 64 print("removing incomplete database %s due to interruption." % |
| 40 config.DATABASE) | 65 config.DATABASE) |
| 66 | |
| 41 shutil.rmtree(config.DATABASE) | 67 shutil.rmtree(config.DATABASE) |
| 68 | |
| 42 signal.signal(signal.SIGINT, int_sig_default_handler) | 69 signal.signal(signal.SIGINT, int_sig_default_handler) |
| 70 # re-raise the signal so the normal signal handling runs. | |
| 43 signal.raise_signal(signal.SIGTERM) | 71 signal.raise_signal(signal.SIGTERM) |
| 44 | 72 |
| 45 def main(backendname, time=time.time, numissues=10): | 73 def main(backendname, time=time.time, numissues=10): |
| 46 global int_sig_default_handler | 74 global int_sig_default_handler |
| 75 | |
| 47 try: | 76 try: |
| 48 backend = importlib.import_module("roundup.backends.back_%s" % | 77 backend = importlib.import_module("roundup.backends.back_%s" % |
| 49 backendname) | 78 backendname) |
| 50 except ImportError: | 79 except ImportError: |
| 80 print("Unable to import %s backend." % backendname) | |
| 51 return | 81 return |
| 52 | 82 |
| 53 times = [] | 83 times = [] |
| 54 | 84 |
| 55 config.DATABASE = os.path.join('_benchmark', '%s-%s'%(backendname, | 85 config.DATABASE = os.path.join('_benchmark', '%s-%s'%(backendname, |
| 56 numissues)) | 86 numissues)) |
| 87 | |
| 88 config.RDBMS_NAME = "rounduptest_%s" % numissues | |
| 89 | |
| 57 if not os.path.exists(config.DATABASE): | 90 if not os.path.exists(config.DATABASE): |
| 58 int_sig_default_handler = signal.signal(signal.SIGINT, rm_db_on_signal) | 91 int_sig_default_handler = signal.signal(signal.SIGINT, rm_db_on_signal) |
| 59 db = backend.Database(config, 'admin') | 92 db = backend.Database(config, 'admin') |
| 60 setupSchema(db, backend) | 93 setupSchema(db, backend) |
| 94 | |
| 95 # if we are re-initializing, delete any existing db | |
| 96 db.clear() | |
| 97 db.commit() | |
| 98 | |
| 61 # create a whole bunch of stuff | 99 # create a whole bunch of stuff |
| 62 db.user.create(**{'username': 'admin', 'roles': 'Admin'}) | 100 db.user.create(**{'username': 'admin', 'roles': 'Admin'}) |
| 63 db.status.create(name="unread") | 101 db.status.create(name="unread") |
| 64 db.status.create(name="in-progress") | 102 db.status.create(name="in-progress") |
| 65 db.status.create(name="testing") | 103 db.status.create(name="testing") |
| 83 signal.signal(signal.SIGINT, int_sig_default_handler) | 121 signal.signal(signal.SIGINT, int_sig_default_handler) |
| 84 else: | 122 else: |
| 85 db = backend.Database(config, 'admin') | 123 db = backend.Database(config, 'admin') |
| 86 setupSchema(db, backend) | 124 setupSchema(db, backend) |
| 87 | 125 |
| 88 sys.stdout.write('%7s: %-6d'%(backendname, numissues)) | 126 sys.stdout.write('%10s: %-6d'%(backendname[:10], numissues)) |
| 89 sys.stdout.flush() | 127 sys.stdout.flush() |
| 90 | 128 |
| 91 times.append(('start', time())) | 129 times.append(('start', time())) |
| 92 | 130 |
| 93 # fetch | 131 # fetch |
| 140 last = stamp | 178 last = stamp |
| 141 print(' %-6.2f'%(last-first)) | 179 print(' %-6.2f'%(last-first)) |
| 142 sys.stdout.flush() | 180 sys.stdout.flush() |
| 143 | 181 |
| 144 if __name__ == '__main__': | 182 if __name__ == '__main__': |
| 183 if len(sys.argv) == 2: | |
| 184 test_databases = sys.argv[1].split() | |
| 185 elif len(sys.argv) > 2: | |
| 186 test_databases = sys.argv[1:] | |
| 187 else: | |
| 188 test_databases = ['anydbm', 'sqlite'] | |
| 189 | |
| 145 # 0 1 2 3 4 5 6 | 190 # 0 1 2 3 4 5 6 |
| 146 # 01234567890123456789012345678901234567890123456789012345678901234 | 191 # 01234567890123456789012345678901234567890123456789012345678901234 |
| 147 print('Test name fetch journl jprops lookup filter filtml TOTAL ') | 192 print('Test name fetch journl jprops lookup filter filtml TOTAL ') |
| 148 for name in 'anydbm sqlite'.split(): | 193 for name in test_databases: |
| 149 main(name) | 194 main(name) |
| 150 for name in 'anydbm sqlite'.split(): | 195 for name in test_databases: |
| 151 main(name, numissues=20) | 196 main(name, numissues=20) |
| 152 for name in 'anydbm sqlite'.split(): | 197 for name in test_databases: |
| 153 main(name, numissues=100) | 198 main(name, numissues=100) |
| 199 | |
| 154 # don't even bother benchmarking the dbm backends > 100! | 200 # don't even bother benchmarking the dbm backends > 100! |
| 155 for name in 'sqlite'.split(): | 201 try: |
| 202 test_databases.remove('anydbm') | |
| 203 except ValueError: | |
| 204 # anydbm not present; this is fine | |
| 205 pass | |
| 206 | |
| 207 for name in test_databases: | |
| 156 main(name, numissues=1000) | 208 main(name, numissues=1000) |
| 157 | 209 |
| 210 for name in test_databases: | |
| 211 main(name, numissues=10000) | |
| 212 | |
| 213 | |
| 158 # vim: set et sts=4 sw=4 : | 214 # vim: set et sts=4 sw=4 : |
