diff -r 031996eb9bb5 CHANGES.txt --- a/CHANGES.txt Mon Jun 27 00:33:31 2022 -0400 +++ b/CHANGES.txt Mon Jun 27 21:41:59 2022 -0400 @@ -172,6 +172,9 @@ i18n object is now also correctly set for the mail interface: previously the 'language' setting in the [mailgw] section seems to have been ignored. Thanks to Marcus Priesch for the patch. +- issue2551212 - speed up wsgi interface by caching the tracker + instance. Hidden behind a feature flag. See upgrading.txt for + details. (Marcus Priesch with feature flag by John Rouillard) 2021-07-13 2.1.0 diff -r 031996eb9bb5 doc/upgrading.txt --- a/doc/upgrading.txt Mon Jun 27 00:33:31 2022 -0400 +++ b/doc/upgrading.txt Mon Jun 27 21:41:59 2022 -0400 @@ -209,6 +209,23 @@ of ps or shell history. The new password will be encrypted using the default encryption method (usually pbkdf2). +Enable performance improvement for wsgi mode (optional) +------------------------------------------------------- + +There is an experimental wsgi performance improvement mode that caches +the loaded roundup instance. This eliminates disk reads that are +incurred on each connection. In one report it improves speed by a +factor of 2 to 3 times. To enable this you should add a feature flag +to your Roundup wsgi wrapper so it looks like:: + + ff = { "cache_tracker": "" } + app = RequestDispatcher(tracker_home, feature_flags=ff) + +to enable this mode. Note that this is experimental and was added +during the 2.0.2 beta period, so it is hidden behind a feature flag. +If you use this and it works better for you please followup with an +email on the roundup-users at lists.sourceforge.net. + Migrating from 2.0.0 to 2.1.0 ============================= diff -r 031996eb9bb5 roundup/cgi/wsgi_handler.py --- a/roundup/cgi/wsgi_handler.py Mon Jun 27 00:33:31 2022 -0400 +++ b/roundup/cgi/wsgi_handler.py Mon Jun 27 21:41:59 2022 -0400 @@ -74,17 +74,24 @@ class RequestDispatcher(object): - def __init__(self, home, debug=False, timing=False, lang=None): + def __init__(self, home, debug=False, timing=False, lang=None, + feature_flags=None): assert os.path.isdir(home), '%r is not a directory' % (home,) self.home = home self.debug = debug self.timing = timing + self.feature_flags= feature_flags or {} + self.tracker = None if lang: self.translator = TranslationService.get_translation(lang, tracker_home=home) else: self.translator = None - self.preload() + + if "cache_tracker" in self.feature_flags: + self.tracker = roundup.instance.open(self.home, not self.debug) + else: + self.preload() def __call__(self, environ, start_response): """Initialize with `apache.Request` object""" @@ -116,8 +123,8 @@ else: form = BinaryFieldStorage(fp=environ['wsgi.input'], environ=environ) - with self.get_tracker() as tracker: - client = tracker.Client(tracker, request, environ, form, + if "cache_tracker" in self.feature_flags: + client = self.tracker.Client(self.tracker, request, environ, form, self.translator) try: client.main() @@ -125,6 +132,16 @@ request.start_response([('Content-Type', 'text/html')], 404) request.wfile.write(s2b('Not found: %s' % html_escape(client.path))) + else: + with self.get_tracker() as tracker: + client = tracker.Client(tracker, request, environ, form, + self.translator) + try: + client.main() + except roundup.cgi.client.NotFound: + request.start_response([('Content-Type', 'text/html')], 404) + request.wfile.write(s2b('Not found: %s' % + html_escape(client.path))) # all body data has been written using wfile return [] diff -r 031996eb9bb5 test/test_liveserver.py --- a/test/test_liveserver.py Mon Jun 27 00:33:31 2022 -0400 +++ b/test/test_liveserver.py Mon Jun 27 21:41:59 2022 -0400 @@ -104,12 +104,17 @@ def create_app(self): '''The wsgi app to start''' + + # define feature flags dict + #ff = {"cache_tracker": ""} # enables caching of tracker on init + ff = {} + if _py3: - return validator(RequestDispatcher(self.dirname)) + return validator(RequestDispatcher(self.dirname, feature_flags=ff)) else: # wsgiref/validator.py InputWrapper::readline is broke and # doesn't support the max bytes to read argument. - return RequestDispatcher(self.dirname) + return RequestDispatcher(self.dirname, feature_flags=ff) def test_start_page(self):