Hi all - just had time this weekend to look further into this. Thank you to suggestions from Iceberg, Yarko and Massimo. I have tried putting table definitions into a module, and also run some timing tests against a Postgres database
As a note, for my previous tests coming out at 12ms page response, those same previous test now come out at 10ms on my computer .. I think just in picking up latest Ubuntu patches etc. something must have changed in my configuration, anyway all the figures below are just a rough guide. Here are the changes I made: db and mail object creation now in modules\application.py. These objects are created once then shared. Setting 'ENABLE_APPLICATION_SCOPE = False' in application.py switches back to standard behaviour (separate db and mail object on every page request) auth,crud,service objects are dependent on the current page request, so I left these in models\db.py. One exception is auth.define_tables - this is run in modules \application.py. Usually runs once only unless ENABLE_APPLICATION_SCOPE is False, then auth.define_tables runs on every page request. Postgres version is 8.4.0-2 installed on same machine web2py is running on. Computer set-up same as for previous test (except for Ubuntu patches mentioned above), the test is to request the index page created by default for a new web2py application. Running 1000 page requests with httperf tool: postgres, compiled, migrate=false, application scope objects disabled, pool_size parameter not set: 58.2ms average page response time postgres, compiled, migrate=false, application scope objects disabled, pool_size=100: 10.9ms average page response time postgres, compiled, migrate=false, application scope objects enabled,pool_size=100: 5.2ms average page response time sqllite, compiled, migrate=false, application scope objects disabled: 10.1ms average page response time sqllite, compiled, migrate=false, application scope objects enabled: 5.4ms average page response time --------- My summary: Sharing objects like the database model definition at the website application scope does give a speed boost, but it is not as big a difference as I thought - I have been pleasantly surprised that the existing per-webpage request evaluation of models was already pretty fast as it is. The difference in Postgres with timings when pool_size is not set at all is significant : This almost warrants defaulting the pool size for this database to 100 anyway, or at least outputting to the log a friendly warning to suggest setting a pool size parameter. I can see some downsides when attempting to use objects at application scope: - I'm not yet sure objects like DAL and Mail will be happy being shared at the application level. Could well be locking / threading issues, would need to investigate further - In general in Python, module source code changes do not get picked up automatically. During development I would work around this with the reload(...) statement - My example shared module probably needs additional try..catch statements to handle if it fails to run, so every webpage request will keep on trying to create the shared objects until they have been successfully created. - There may be good reason to refresh these shared objects periodically anyway, maybe tie the shared object creation to a cron job. If I could be confident there are no threading issues then using shared objects could be an option. But until then I am now happier sticking with the standard setup - putting maybe quite complex model structures in the regular model folder, these will be evaluated on every webpage request, but the site will still run plenty fast - good enough for me anyway! Here is my updated db.py and module source code at the end of this message. Just add both to a blank application created by the web2py admin. Cheers, - Alex -- db.py model file, pulling in shared 'application scope' objects: # coding: utf8 from gluon.tools import * import applications.perftest.modules.application as app #Get objects shared between page requests app.Helper.get_application_scope(globals()) #Rest of this file sets up per-page model state: if not globals().has_key('auth'): auth=Auth(globals(),db) auth.settings.hmac_key='6944f00d-1758-41e4-8fdb-625b0be17e1a' auth.settings.mailer=mail # for user email verification auth.settings.registration_requires_verification = True auth.settings.registration_requires_approval = True auth.messages.verify_email = \ 'Click on the link http://.../user/verify_email/%(key)s to verify your email' crud=Crud(globals(),db) crud.settings.auth=auth #Connect gae session if required if request.env.web2py_runtime_gae: session.connect(request, response, db=db) #Set up service for this request from gluon.tools import * service=Service(globals()) ---------------------------------------- application.py module file: # coding: utf8 from gluon.storage import Storage from gluon.sql import SQLDB, SQLField, DAL, Field from gluon.tools import * import thread ENABLE_APPLICATION_SCOPE = True class Helper(object): singleton = None def __init__(self, environment): request = environment['request'] self.storage = Storage() self.storage.db = self.get_db(request) self.storage.mail = self.get_mail() @staticmethod def get_application_scope(globals): if ENABLE_APPLICATION_SCOPE: if Helper.singleton is None: locker = thread.allocate_lock() locker.acquire() Helper.singleton = Helper(globals) Helper.singleton.init_auth(globals); locker.release() globals.update(Helper.singleton.storage) else: request_scope = Helper(globals) request_scope.storage.auth = request_scope.init_auth (globals) globals.update(request_scope.storage) def get_db(self, request): if request.env.web2py_runtime_gae: db = DAL('gae') else: #db = DAL('sqlite://storage.sqlite') db=DAL('postgres://testuser:t...@localhost:5432/web2py', pool_size=100) for i in range(1, 5): db.define_table('perftest' + str(i), SQLField('string1','string'), SQLField('text1','text'), SQLField('blob1','blob'), SQLField('password1','password'), SQLField('upload1','upload'), SQLField('boolean1','boolean'), SQLField('integer1','integer'), SQLField('double1','double'), SQLField('date1','date'), SQLField('time1','time'), SQLField('datetime1','datetime'),migrate=False) return db def get_mail(self): mail=Mail() # mailer mail.settings.server='smtp.gmail.com:587' # your SMTP server mail.settings.sender='y...@gmail.com' # your email mail.settings.login='username:password' # your credentials or None return mail #Just used to initialise auth database tables def init_auth(self, globals): auth=Auth(globals, self.storage.db) auth.define_tables(migrate=False) return auth --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "web2py-users" group. To post to this group, send email to web2py@googlegroups.com To unsubscribe from this group, send email to web2py+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/web2py?hl=en -~----------~----~----~----~------~----~------~--~---