Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Jul 1995 09:28:14 -0700
From:      Bill Paul <wpaul>
To:        CVS-commiters, cvs-gnu
Subject:   cvs commit: src/gnu/usr.sbin/ypserv svc_run.c Makefile server.c yp_svc.c
Message-ID:  <199507121628.JAA10955@freefall.cdrom.com>

next in thread | raw e-mail | index | archive | help
wpaul       95/07/12 09:28:14

  Modified:    gnu/usr.sbin/ypserv  Makefile server.c yp_svc.c
  Added:       gnu/usr.sbin/ypserv  svc_run.c
  Log:
  ypserv performance improvements:
  
  - There are two cases where the server can potentially block for a long
    time while servicing a request: when handling a yp_all() request, which
    could take a while to complete if the map being transfered is large
    (e.g. 'ypcat passwd' where passwd.byname has 10,000 entries in it),
    and while doing DNS lookups when in SunOS compat mode (with the -dns
    flag), since some DNS lookups can take a long time to complete. While
    ypserv is blocked, other clients making requests to the server will
    also block. To fix this, we fork() ypall and DNS lookups into subprocesses
    and let the parent ypserv process go on servicing other incoming
    requests.
  
    We place a cap on the number of simultaneous processes that ypserv can
    fork (set at 20 for now) and go back to 'linear mode' if it hits the
    limit (which just means it won't fork() anymore until the number of
    simultaneous processes drops under 20 again). The cap does not apply
    to fork()s done as a result of ypxfr calls, since we want to do our
    best to insure that map transfers from master servers succeed.
  
    To make this work, we need our own special copy of svc_run() so that
    we can properly terminate child processes once the RPC dispatch
    functions have run.
  
    (I have no idea what SunOS does in this situation. The only other
    possibility I can think of is async socket I/O, but that seems
    like a headache and a half to implement.)
  
  - Do the politically correct thing and use sigaction() instead of
    signal() to install the SIGCHLD handler and to ignore SIGPIPEs.
  
  - Doing a yp_all() is sometimes slow due to the way read_database() is
    implemented. This is turn is due to a certain deficiency in the DB
    hash method: the R_CURSOR flag doesn't work, which means that when
    handed a key and asked to return the key/data pair for the _next_
    key in the map, we have to reset the DB pointer to the start of the
    database, step through until we find the requested key, step one
    space ahead to the _next_ key, and then use that. (The original ypserv
    code used GDBM has a function called gdbm_nextkey() that does
    this for you.) This can get really slow for large maps. However,
    when doing a ypall, it seems that all database access are sequential,
    so we can forgo the first step (the 'search the database until we find
    the key') since the database should remain open and the cursor
    should be positioned at the right place until the yp_all() call
    finishes. We can't make this assumption for arbitrary yp_first()s
    and yp_next()s however (since we may have requests from several clients
    for different maps all arriving at different times) so those we have
    to handle the old way.
  
    (This would be much easier if R_CURSOR really worked. Maybe I should
     be using something other than the hash method.)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199507121628.JAA10955>