Received: (from majordom@localhost) by hyperreal.com (8.8.5/8.8.5) id QAA26446; Sun, 29 Jun 1997 16:49:23 -0700 (PDT) Received: from sierra.zyzzyva.com (ppp0-sierra.zyzzyva.com [208.214.59.46]) by hyperreal.com (8.8.5/8.8.5) with ESMTP id QAA26440 for ; Sun, 29 Jun 1997 16:49:18 -0700 (PDT) Received: from sierra (localhost [127.0.0.1]) by sierra.zyzzyva.com (8.8.5/8.8.2) with ESMTP id SAA08770 for ; Sun, 29 Jun 1997 18:45:21 -0500 (CDT) Message-Id: <199706292345.SAA08770@sierra.zyzzyva.com> X-Mailer: exmh version 2.0gamma 1/27/96 To: new-httpd@apache.org Subject: Re: [PATCH] run_method performance improvement In-reply-to: dgaudet's message of Sun, 29 Jun 1997 14:45:16 -0700. X-uri: http://www.zyzzyva.com/ Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Sun, 29 Jun 1997 18:45:21 -0500 From: Randy Terbush Sender: new-httpd-owner@apache.org Precedence: bulk Reply-To: new-httpd@apache.org +1 for HEAD. I've been running this since you first offered it. > I've mentioned this one before. Last time I profiled this it cut the > run_method from 7% to 1% of total CPU time on the default module list. > > I want to commit this one tomorrow too... I figure I might as well break > it badly in multiple ways all on the same day :) > > Dean > > Index: CHANGES > =================================================================== > RCS file: /export/home/cvs/apache/src/CHANGES,v > retrieving revision 1.308 > diff -c -3 -r1.308 CHANGES > *** CHANGES 1997/06/29 18:26:56 1.308 > --- CHANGES 1997/06/29 21:42:19 > *************** > *** 1,5 **** > --- 1,8 ---- > Changes with Apache 1.3 > > + *) run_method optimized to avoid needless scanning over NULLs in the > + module list. [Dean Gaudet] > + > *) Add a ListenBacklog directive to control the backlog parameter > passed to listen(). Also change the default to 511 from 512. > [Marc Slemko] > Index: http_config.c > =================================================================== > RCS file: /export/home/cvs/apache/src/http_config.c,v > retrieving revision 1.54 > diff -c -3 -r1.54 http_config.c > *** http_config.c 1997/06/29 19:05:20 1.54 > --- http_config.c 1997/06/29 21:42:22 > *************** > *** 144,150 **** > void * > merge_per_dir_configs (pool *p, void *base, void *new) > { > ! void **conf_vector = (void **)pcalloc(p, sizeof(void*) * total_modules); > void **base_vector = (void **) base; > void **new_vector = (void **) new; > module *modp; > --- 144,150 ---- > void * > merge_per_dir_configs (pool *p, void *base, void *new) > { > ! void **conf_vector = (void **)palloc(p, sizeof(void*) * total_modules); > void **base_vector = (void **) base; > void **new_vector = (void **) new; > module *modp; > *************** > *** 250,269 **** > * do the dirty work of slogging through the module structures. > */ > > ! int > run_method (request_rec *r, int offset, int run_all) > { > ! module *modp; > ! for (modp = top_module; modp; modp = modp->next) { > ! handler mod_handler = *(handler *)(offset + (char *)(modp)); > > ! if (mod_handler) { > int result; > > - Explain1("Run %s",ShowMethod(modp,offset)); > result = (*mod_handler)(r); > > - Explain2("%s returned %d",ShowMethod(modp,offset),result); > if (result != DECLINED && (!run_all || result != OK)) > return result; > } > --- 250,350 ---- > * do the dirty work of slogging through the module structures. > */ > > ! /* > ! * Optimized run_method routines. The observation here is that many modules > ! * have NULL for most of the methods. So we build optimized lists of > ! * everything. If you think about it, this is really just like a sparse array > ! * implementation to avoid scanning the zero entries. > ! */ > ! static const int method_offsets[] = { > ! XtOffsetOf (module, translate_handler), > ! XtOffsetOf (module, check_user_id), > ! XtOffsetOf (module, auth_checker), > ! XtOffsetOf (module, access_checker), > ! XtOffsetOf (module, type_checker), > ! XtOffsetOf (module, fixer_upper), > ! XtOffsetOf (module, logger), > ! XtOffsetOf (module, header_parser) > ! }; > ! #define NMETHODS (sizeof (method_offsets)/sizeof (method_offsets[0])) > ! > ! static struct { > ! int translate_handler; > ! int check_user_id; > ! int auth_checker; > ! int access_checker; > ! int type_checker; > ! int fixer_upper; > ! int logger; > ! int header_parser; > ! } offsets_into_method_ptrs; > ! > ! /* > ! * This is just one big array of method_ptrs. It's constructed such that, > ! * for example, method_ptrs[ offsets_into_method_ptrs.logger ] is the first > ! * logger function. You go one-by-one from there until you hit a NULL. > ! * This structure was designed to hopefully maximize cache-coolness. > ! */ > ! static handler *method_ptrs; > ! > ! /* routine to reconstruct all these shortcuts... called after every > ! * add_module. > ! * XXX: this breaks if modules dink with their methods pointers > ! */ > ! static void > ! build_method_shortcuts (void) > ! { > ! module *modp; > ! int how_many_ptrs; > ! int i; > ! int next_ptr; > ! handler fp; > ! > ! if (method_ptrs) { > ! /* free up any previous set of method_ptrs */ > ! free (method_ptrs); > ! } > ! > ! /* first we count how many functions we have */ > ! how_many_ptrs = 0; > ! for (modp = top_module; modp; modp = modp->next) { > ! for (i = 0; i ! if (*(handler *)(method_offsets[i] + (char *)modp)) { > ! ++how_many_ptrs; > ! } > ! } > ! } > ! method_ptrs = malloc ((how_many_ptrs+NMETHODS)*sizeof (handler)); > ! next_ptr = 0; > ! for (i = 0; i ! /* XXX: This is an itsy bit presumptuous about the alignment > ! * constraints on offsets_into_method_ptrs. I can't remember if > ! * ANSI says this has to be true... -djg */ > ! ((int *)&offsets_into_method_ptrs)[i] = next_ptr; > ! for (modp = top_module; modp; modp = modp->next) { > ! fp = *(handler *)(method_offsets[i] + (char *)modp); > ! if (fp) { > ! method_ptrs[next_ptr++] = fp; > ! } > ! } > ! method_ptrs[next_ptr++] = NULL; > ! } > ! } > ! > ! > ! static int > run_method (request_rec *r, int offset, int run_all) > { > ! int i; > ! > ! for (i = offset; method_ptrs[i]; ++i ) { > ! handler mod_handler = method_ptrs[i]; > > ! if (mod_handler) { > int result; > > result = (*mod_handler)(r); > > if (result != DECLINED && (!run_all || result != OK)) > return result; > } > *************** > *** 273,299 **** > } > > int translate_name(request_rec *r) { > ! return run_method (r, XtOffsetOf (module, translate_handler), 0); > } > > int check_access(request_rec *r) { > ! return run_method (r, XtOffsetOf (module, access_checker), 1); > } > > int find_types (request_rec *r) { > ! return run_method (r, XtOffsetOf (module, type_checker), 0); > } > > int run_fixups (request_rec *r) { > ! return run_method (r, XtOffsetOf (module, fixer_upper), 1); > } > > int log_transaction (request_rec *r) { > ! return run_method (r, XtOffsetOf (module, logger), 1); > } > > int header_parse (request_rec *r) { > ! return run_method (r, XtOffsetOf (module, header_parser), 1); > } > > /* Auth stuff --- anything that defines one of these will presumably > --- 354,380 ---- > } > > int translate_name(request_rec *r) { > ! return run_method (r, offsets_into_method_ptrs.translate_handler, 0); > } > > int check_access(request_rec *r) { > ! return run_method (r, offsets_into_method_ptrs.access_checker, 1); > } > > int find_types (request_rec *r) { > ! return run_method (r, offsets_into_method_ptrs.type_checker, 0); > } > > int run_fixups (request_rec *r) { > ! return run_method (r, offsets_into_method_ptrs.fixer_upper, 1); > } > > int log_transaction (request_rec *r) { > ! return run_method (r, offsets_into_method_ptrs.logger, 1); > } > > int header_parse (request_rec *r) { > ! return run_method (r, offsets_into_method_ptrs.header_parser, 1); > } > > /* Auth stuff --- anything that defines one of these will presumably > *************** > *** 302,312 **** > */ > > int check_user_id (request_rec *r) { > ! return run_method (r, XtOffsetOf (module, check_user_id), 0); > } > > int check_auth (request_rec *r) { > ! return run_method (r, XtOffsetOf (module, auth_checker), 0); > } > > int invoke_handler (request_rec *r) > --- 383,393 ---- > */ > > int check_user_id (request_rec *r) { > ! return run_method (r, offsets_into_method_ptrs.check_user_id, 0); > } > > int check_auth (request_rec *r) { > ! return run_method (r, offsets_into_method_ptrs.auth_checker, 0); > } > > int invoke_handler (request_rec *r) > *************** > *** 391,396 **** > --- 472,479 ---- > if (m->module_index == -1) { > m->module_index = num_modules++; > } > + /** XXX: this will be slow if there's lots of add_modules */ > + build_method_shortcuts (); > } > > void setup_prelinked_modules ()