ten thousand small processes

D. J. Bernstein djb at cr.yp.to
Tue Jun 24 23:05:58 PDT 2003


As I said, I don't particularly care about the text segment. I'm not
talking about ten thousand separate programs.

Why does the memory manager keep the stack separate from data? Suppose a
program has 1000 bytes of data+bss. You could organize VM as follows:

                   0x7fffac18    0x7fffb000             0x80000000 
     <---- stack   data+bss      text, say 5 pages      heap ---->

As long as the stack doesn't chew up more than 3096 bytes and the heap
isn't used, there's just one page per process.

As for page tables: Instead of allocating space for a bunch of nearly
identical page tables, why not overlap page tables, with the changes
copied on a process switch?

As for 39 pages of VM, mostly stack: Can the system actually allocate
390000 pages of VM? I'm only mildly concerned with the memory-management
time; what bothers me is the loss of valuable address space. I hope that
this 128-kilobyte stack carelessness doesn't reflect a general policy of
dishonest VM allocation (``overcommitment''); I need to be able to
preallocate memory with proper error detection, so that I can guarantee
the success of subsequent operations.

As for malloc()'s careless use of memory: Is it really asking so much
that a single malloc(1) not be expanded by a factor of 16384?

Here's a really easy way to improve malloc(). Apparently, right now,
there's no use of the space between the initial brk and the next page
boundary. Okay: allocate that space in the simplest possible way---

   static wherewenormallystart = 0;
   static freebie;

   malloc(n)
   {
     if (!wherewenormallystart) {
       wherewenormallystart = rounduptopage(sbrk(0));
       freebie = wherewenormallystart - rounduptoalign(sbrk(0));
     }
     n = rounduptoalign(n);
     if (n < freebie) {
       freebie -= n;
       if (sbrk(0) <= wherewenormallystart) brk(wherewenormallystart - freebie);
       return wherewenormallystart - freebie - n;
     }
     do what we normally do;
   }

   free(x)
   {
     if (x < wherewenormallystart) return;
     do what we normally do;
   }

---with no waste of space and practically no waste of time. Maybe add
8192 to wherewenormallystart; this is lots of room for people who know
how to write small programs, and the cost is unnoticeable for people who
don't.

(Quite a few of my programs simulate this effect by checking for space
in a bss array, typically 2K. But setting aside the right amount of
space would mean compiling, inspecting the brk alignment, and
recompiling. I also feel bad chewing up space on systems where malloc()
actually knows what it's doing.)

As for the safety of writing code that makes malloc() fail horribly:
After the Solaris treatment of BSD sockets, and the ``look, Ma, I can
make an only-slightly-broken imitation of poll() using select()!''
epidemic, I don't trust OS distributors to reserve syscall names for
actual syscalls. I encounter more than enough portability problems
without going out of my way to look for them.

---D. J. Bernstein, Associate Professor, Department of Mathematics,
Statistics, and Computer Science, University of Illinois at Chicago


More information about the freebsd-performance mailing list