NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

bin/60607: /etc/rc does too much throw-away work and is needlessly slow on constrained systems



>Number:         60607
>Category:       bin
>Synopsis:       /etc/rc does too much throw-away work and is needlessly slow on constrained systems
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Aug 17 05:35:00 +0000 2026
>Originator:     Jason Thorpe
>Release:        NetBSD 11.99.7
>Organization:
Retrogrouches'R'Us
>Environment:
Any sufficiently constrained machine will do, but wrap030 is the exemplar.
>Description:
NetBSD's /etc/rc and /etc/rc.d are a well-designed facility that provide a good mix of flexibility, extensibility, and ease of configuration.  However, the implementation performs quite a lot of work that, on constrained systems, leads to frustratingly long boot times.  Part of this issue stems from per-service isolation implemented using sub-shells. the "rc_fast_and_loose" config setting was introduced to paper over this.

To illustrate the point, boot times of ~13 minutes have been observed on a 25MHz 68030 with a PIO-only ATA disk interface.  Instrumentation showed that huge amounts of time, with no progress reporting, were being spent between start-up messages running start-up scripts that did nothing because they were not enabled.

The issue stems from the fact that a lot of processing work goes into an rc.d script even if the rcvar that controls it is set to NO.  This is throw-away work that consumes time for no benefit.
>How-To-Repeat:
Boot even a minimally configured system on a constrained machine.  Real 32-bit SPARC, VAX, and m68k hardware are more likely to exhibit the performance problem of the system.
>Fix:
I've devised a simple solution to the problem that's minimally invasive and, on the wrap030 homebrew, cuts the boot time (with ldconfig=NO) from ~13 minutes to ~7 minutes.

The solution is comprised of two parts:

1. Some small modifications to /etc/rc.subr that add a new standard "doeswork" directive to rc.d scripts.  This directive interrogates the script to ask if it's going to do any work.  The answer is YES if the script's rcvar is set to YES or if the script is not controlled by an rcvar.  Otherwise, it means the script's rcvar is set to NO and the script will thus do no useful work at boot time.

2. Another small change to /etc/rc where the real work of invoking the rc.d scripts is performed.  This second change introduces the notion of the "rcorder.cache".  At boot time, if it is determined that the cache needs to be rebuilt, then all of the rc.d scripts are interrogated in rcorder-order to see if they will do work.  If so, they're added to the list, otherwise they are ignored.  Once the list is built, then the list is invoked to start each service in the normal way.  The list is saved in the "rcorder.cache" and consulted at the next boot.  The cache is invalidated by modifying /etc/rc.conf, /etc/rc.d, or by manually removing /etc/rcorder.cache.

On some selected sample systems, this reduced the number of rc.d scripts that had to be run by ~66% while fully preserving the dependency ordering.  On very I/O-constrained systems, this cut system boot time by ~50%.

Patch that implements this change is here:

    https://www.netbsd.org/~thorpej/rcorder-cache-diff.txt

It almost certainly need some additional polish work, and probably some integration with etcupdate(8).




Home | Main Index | Thread Index | Old Index