Re: fork: out of memory

Zlatko Calusic (Zlatko.Calusic@CARNet.hr)
25 Nov 1997 03:25:47 +0100


"David E. Fox" <dfox@belvdere.vip.best.com> writes:

> With 2.1.65 I've noticed a couple 'fork: out of memory'
> messages that I think are spurious. At least there was
> plenty of free memory left at the times I got these
> messages. The last time I got it it came from cron's
> run-parts script (I am on a Red Hat 4.2 system) and
> it was mailed to root.
>
> I also got an awk help display on the screen.
>
> Anyone else seen this?
>

Problem is because of memory fragmentation. In fact, two things work
in cooperation to bring us such ridiculous messages:

1) Slab allocator.

It needs 8!!! contiguos pages to allocate one files_struct in
files_cachep cache. Well, other 6 (or 5?) allocations will be fast
because they will come from already allocated slab, but after
that... well it depends on luck. :)

2) files_struct itself:

'Cause it's just slightly longer than one page -> 4384 (at least on
32bit architectures where PAGE_SIZE = 4096). To avoid big internal
fragmentation, slab allocator must! use lots of pages. So it's not
that big fault of the slab allocator. Maybe it could allow bigger
loses but that would be a workaround not a solution.

All this can be verified (with SLAB_STATS == 1) in /proc/slabinfo:

files_cache 42 49 7 7 56 53 17680 23 16 0
^^^^^^
56/7 = 8 pages - gfp of order 3

Knowing that even gfp's of order 2 like to fail occasionally (and
somethimes regularly :})...

Proposition:

struct files_struct is currently defined like:

struct files_struct {
int count;
fd_set close_on_exec;
fd_set open_fds;
struct file * fd[NR_OPEN];
};

Maybe it would be a wise idea to make few pointers instead of
fd[NR_OPEN]. Every pointer would point to a smaller table of let's say
64 file descriptors and would be allocated as needed. First such table
would be in files_struct itself.

E.g.

struct files_struct {
int count;
fd_set close_on_exec;
fd_set open_fds;
struct file * fd[64]; /* 64 instead of 1024 */
struct file ** fd_a; /* allocate as necessary */
struct file ** fd_b;
struct file ** fd_c;
struct file ** fd_d;
...
};

This could be modified, so that fd_a, fd_b ... point to bigger and
bigger tables, so they can be allocated faster (something like 64,
128, 256, 512. All added = NR_OPEN).

I would like to hear a second opinion on this!!!

Also, is there any reason that fd_set (and other structures) couldn't
be increased to support 4096 open fd's? I believe with corrections I
propose, we wouldn't lose any more memory, but programs like squid and
news server would be happier (and any other which use lots of fd's).

BTW, right now, there are 46 processes on my machine. Neither one of
them use more than 64 fd's. Even such a bloat like Netscape uses only
26. To allocate all needed files_struct, kernel used more than 200KB
of nonpageable memory which is mostly (95%) unused!!!

Regards,

-- 
Posted by Zlatko Calusic           E-mail: <Zlatko.Calusic@CARNet.hr>
---------------------------------------------------------------------
	 No sense being pessimistic. It wouldn't work anyway.