From nobody@FreeBSD.org  Wed Nov 30 15:37:08 2005
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 7308716A41F
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 30 Nov 2005 15:37:08 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 1C7B143D46
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 30 Nov 2005 15:37:08 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id jAUFb7no050054
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 30 Nov 2005 15:37:07 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id jAUFb7Jb050053;
	Wed, 30 Nov 2005 15:37:07 GMT
	(envelope-from nobody)
Message-Id: <200511301537.jAUFb7Jb050053@www.freebsd.org>
Date: Wed, 30 Nov 2005 15:37:07 GMT
From: Oliver Brandmueller <ob@e-gitt.net>
To: freebsd-gnats-submit@FreeBSD.org
Subject: top startup is very slow on system with many users
X-Send-Pr-Version: www-2.3

>Number:         89762
>Category:       bin
>Synopsis:       [patch] top(1) startup is very slow on system with many users
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    edwin
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov 30 15:40:05 GMT 2005
>Closed-Date:    
>Last-Modified:  Sun Dec 25 21:20:08 UTC 2011
>Originator:     Oliver Brandmueller
>Release:        RELENG_6
>Organization:
>Environment:
FreeBSD waikiki.visp.de 6.0-STABLE FreeBSD 6.0-STABLE #0: Tue Nov 29 18:12:02 CET 2005     root@waikiki.visp.de:/usr/obj/usr/src/sys/APP-32-FBSD6  i386
>Description:
My servers have >80k accounts via nss_ldap. Startup of top is very slow, because top read the whole list of system users to find out which is the longest username. This takes several seconds for starting up top on an idle machine of decent speed.

My current patch replaces the username advance code if a variable is defined at compile time. I suggest dropping the current behaviour completely, because the routine is for cosmetic changes to top output only while really being a pain in the ass if you have lots of users.
>How-To-Repeat:
put 80k users on your system (probably use a slow user database like LDAP or NIS) and start top.
>Fix:
diff -c usr.bin/top.orig/Makefile usr.bin/top/Makefile
*** usr.bin/top.orig/Makefile   Sat Feb  9 00:07:35 2002
--- usr.bin/top/Makefile        Wed Nov 30 00:21:29 2005
***************
*** 7,12 ****
--- 7,21 ----
  CFLAGS+= -DHAVE_GETOPT -DHAVE_STRERROR -I${.CURDIR} -I${TOPDIR} -I. -DORDER
  
  #
+ # In large setups advancing through the complete usertable to find the
+ # maximum length of a username means a long startup time. If you define
+ # TOP_NO_NAMELEN in /etc/make.conf the maximum length is considered to
+ # be a good value
+ .if defined(TOP_NO_NAMELEN)
+ CFLAGS+= -DTOP_NO_NAMELEN
+ .endif
+ 
+ #
  # The table size should be a prime number approximately twice as
  # large as the number of lines in /etc/passwd.  The default number
  # is 20011, use /etc/make.conf to override this.
diff -c usr.bin/top.orig/machine.c usr.bin/top/machine.c
*** usr.bin/top.orig/machine.c  Wed May 18 15:42:51 2005
--- usr.bin/top/machine.c       Wed Nov 30 16:34:02 2005
***************
*** 235,240 ****
--- 235,246 ----
            modelen != sizeof(smpmode))
                smpmode = 0;
  
+ #ifdef TOP_NO_NAMELEN
+       if(smpmode)
+               namelength = SMPUNAMELEN;
+       else
+               namelength = UPUNAMELEN;
+ #else
        while ((pw = getpwent()) != NULL) {
                if (strlen(pw->pw_name) > namelength)
                        namelength = strlen(pw->pw_name);
***************
*** 243,248 ****
--- 249,255 ----
                namelength = SMPUNAMELEN;
        else if (namelength > UPUNAMELEN)
                namelength = UPUNAMELEN;
+ #endif
  
        kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open");
        if (kd == NULL)

>Release-Note:
>Audit-Trail:

From: Gavin Atkinson <gavin.atkinson@ury.york.ac.uk>
To: bug-followup@FreeBSD.org, ob@e-gitt.net
Cc:  
Subject: Re: bin/89762: [patch] top(1) startup is very slow on system with
	many users
Date: Fri, 04 May 2007 15:43:51 +0100

 This is still a problem with 6.2-STABLE.  On a 2.2GHz amd64 machine with
 ~20,000 NIS users, "top -b" takes 74 seconds before displaying any
 output and generates significant load on the NIS servers.
 
 wiggum# time top -b
 last pid: 1742; load averages: 0.00, 0.00, 0.00 up 36+03:20:25  15:39:47
 32 processes:  1 running, 31 sleeping
 
 Mem: 82M Active, 191M Inact, 108M Wired, 213M Buf, 1498M Free
 Swap: 3072M Total, 3072M Free
 [process list snipped]
 
 0.243u 0.719s 1:14.88 1.2%      60+1253k 0+0io 0pf+0w
 
 Gavin

From: Gavin Atkinson <gavin.atkinson@ury.york.ac.uk>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/89762: [patch] top(1) startup is very slow on system with
	many users
Date: Fri, 04 May 2007 15:57:28 +0100

 This is a duplicate of PR bin/20799, although this one contains a more
 complete patch.  This PR should remain open, 20799 should be closed.

From: Rong-En Fan <rafan@FreeBSD.org>
To: freebsd-gnats-submit@FreeBSD.org
Cc: bushman@FreeBSD.org
Subject: Re: bin/89762: [patch] top(1) startup is very slow on system with
	many users
Date: Fri, 4 May 2007 23:02:12 +0800

 We use similar patch on our system. I think the real solution
 is cached(8) in CURRENT.

From: Gavin Atkinson <gavin.atkinson@ury.york.ac.uk>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/89762: [patch] top(1) startup is very slow on system with
	many users
Date: Wed, 9 Jan 2008 18:03:01 +0000

 Using cached(8) is only a partial solution though, as the first time top(1)
 is run the entire nismap will have to be pulled from the NIS servers.  In
 my example where it took 74 seconds, most of the delay is probably down to
 the relatively slow NIS servers.  cached(8) won't help with that, for the
 first run of top(1) at least.
Responsible-Changed-From-To: freebsd-bugs->edwin 
Responsible-Changed-By: edwin 
Responsible-Changed-When: Thu Sep 25 22:03:56 UTC 2008 
Responsible-Changed-Why:  
Grab it on the evneing of the 3.8b1 import for evaluation. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=89762 

From: Alexander Best <arundel@freebsd.org>
To: bug-followup@freebsd.org
Cc:  
Subject: Re: bin/89762: [patch] top(1) startup is very slow on system with many users
Date: Sun, 25 Dec 2011 21:10:55 +0000

 the issue seems to be that top reads in the entire list of username, because it
 calculates the legth of the username with the most characters in it. a solution
 would be that top only calculates the length of the usernames with active
 processes running. during each refresh of top however that needs to be
 re-calculated. still i believe that should be faster than the way top makes up
 the length of the USERNAME column atm.
 
 a more drastic solution would be to use a fixed width of the username column.
 how about 16 characters? that should be enough in a standard envirement to
 distinguish between each username.
 
 of course SUPERDUPERAMASINGUSER1 and SUPERDUPERAMASINGUSER2 wouldn't be
 distinguishable, but i guess keeping usernames sensible should be the admin's
 responsibility.
 
 cheers.
 alex
>Unformatted:
