[net.sources] more efficient bnproc

chuqui@nsc.UUCP (Chuq Von Rospach) (06/24/84)

while ripping apart inews and the batching schemes during the Great Inews
Rewrite pilgrimage, I found an inefficiency problem in Peter Gross's bnproc
that was rather easy to fix, so I did until I can get bnproc integrated
into inews. For every message shoved into bnproc it was calling popen() to
spawn rnews. Well, popen() uses the wonderful system() call, which spawns a
shell which spawns rnews. That is TWO processes per message. When you
consider we are averaging 300-500 messages a day, that is a lot of
overhead. This version of bnproc looks in "defs.h" for the home of rnews
(defined by the string RNEWS, normally /usr/bin) and forks and execl()'s 
it directly. My timing tests show that the original version used about 2.5
CPU seconds per message (with two processes) while this version uses about
2.3 CPU seconds per message (doesn't sound like much, but forking is an
expensive process when we are talking about 500 of them!). This should help
sites using this batch scheme until I teach inews enough so we don't fork
at all.

chuq 

P.S. I've also gotten bnuuxqt.c running under 4.2. The changes were easy,
but if you are interested in a copy, let me know.


--- bnproc.c ---
# ifndef NOSCCS
static char *sccsid = "%W%	%G%";
# endif
/*****************************************************************************
* bnproc: break up and process the batched news files                        *
*****************************************************************************/
#include <stdio.h>
#include <signal.h>
#include "../src/defs.h"

char buf[80];
FILE *prnews();

main(ac, av)
char **av;
{
	nice(40);			/* be VERY nice */
	while(--ac > 0)
		process(*++av);
	exit(0);
}

process(fn)
char *fn;
{
	long size;
	register FILE *ifn, *pfn;

	if ((ifn = fopen(fn, "r")) == NULL) return;
	while(fgets(buf, sizeof(buf), ifn) != NULL)
	{
		long atol();
		register c;

		size = atol(buf);
		if(size <= 0)
			continue;
		pfn = prnews();     /* spawn rnews efficiently */
		while(--size >= 0 && (c = getc(ifn)) != EOF)
			putc(c, pfn);
		pclose(pfn);
	}
	fclose(ifn);
}
/*
 * This is a modified version of popen.  Rather than
 * forking off a shell, you get a bare process. 
 * this process will be rnews, with no arguments. This is for
 * efficiency reasons since the standard popen spawns a shell
 * AND the process, and two processes per message is a bit much.
 */
#define	RDR	0
#define	WTR	1
static	int	mopen_pid[20];

FILE *
prnews()
{
	int p[2];
	register myside, hisside, pid;
	char *sendto = NULL;

	if(pipe(p) < 0)
		return NULL;
	myside = p[WTR];
	hisside = p[RDR];
	if((pid = fork()) == 0) {
		/* myside and hisside reverse roles in child */
		close(myside);
		close(0);
		dup(hisside);
		close(hisside);
		execl(RNEWS, "rnews", 0);
		_exit(1);
	}
	if(pid == -1)
		return NULL;
	mopen_pid[myside] = pid;
	close(hisside);
	return(fdopen(myside, "w"));
}
-- 
From the ledge of the seventh cornice:			Chuq Von Rospach
{amd,fortune,hplabs,ihnp4}!nsc!chuqui			(408) 733-2600 x242

You can't always get what you want, but if you try sometime
you just might find, you'll get what you need! -- Rolling Stones