[comp.lang.c] avoiding stdio

brnstnd@stealth.acf.nyu.edu (01/21/90)

In article <21689@mimsy.umd.edu> chris@mimsy.umd.edu (Chris Torek) writes:
> In most cases, there is a definite disadvantage in speed in avoiding stdio.

What Chris means is that in most cases, there is a definite disadvantage
in speed in avoiding buffering. There's also a definite disadvantage in
programmer time in rewriting all the standard libraries.

There is, however, a definite advantage in speed in using the facilities
of the operating system without stdio to get in the way. I have several
programs that run twice as fast because they avoid stdio and do their
own buffering.

By the way, Chris, will the new BSD stdio have a working putc(c,*f++)?

---Dan

chris@mimsy.umd.edu (Chris Torek) (01/21/90)

In article <28888@stealth.acf.nyu.edu> brnstnd@stealth.acf.nyu.edu writes:
>What Chris means is that in most cases, there is a definite disadvantage
>in speed in avoiding buffering. There's also a definite disadvantage in
>programmer time in rewriting all the standard libraries.

There is also the problem that `appropriate buffering' can change with
a new release of the system.  For instance, the OS/2 file system is
much like the BSD FFS in some ways, and there an advantage to using
larger buffers (under older PC OSes, a `disk block' is smaller than
under OS/2).

>There is, however, a definite advantage in speed in using the facilities
>of the operating system without stdio to get in the way.

This can indeed happen, since stdio tends to do too much data copying:
e.g., the loop

	while (fgets(s, n, rstream) != NULL)
		(void) fputs(s, wstream);

works by reading from rstream to a buffer, copying the buffer into
s, copying s into a buffer for wstream, and then writing to wstream.

>By the way, Chris, will the new BSD stdio have a working putc(c,*f++)?

The ANSI standard says that putc(c, *f++) is a no-no.  As a side
effect of being an inline function under gcc, however, it will happen
to work there.  This putc() handles full, line, and no buffering, and
the macro is rather complicated.  (__s stands for `stdio'; the __
version of putc exists so that it is easy to define a function version
in the library.)

[excerpt 1]
 * The following always hold:
 *
 *	if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
 *		_lbfsize is -_bufsize, else _lbfsize is 0
 *	if _flags&__SRD, _w is 0
 *	if _flags&__SWR, _r is 0
 *
 * This ensures that the getc and putc macros (or inline functions) never
 * try to write or read from a file that is in `read' or `write' mode.
 * (Moreover, they can, and do, automatically switch from read mode to
 * write mode, and back, on "r+" and "w+" files.)
 *
 * _lbfsize is used only to make the inline line-buffered output stream
 * code as compact as possible.

[excerpt 2]
#ifdef __GNUC__
static __inline int __sputc(int _c, FILE *_p) {
	if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
		return (*_p->_p++ = _c);
	else
		return (__swbuf(_c, _p));
}
#else
/*
 * This has been tuned to generate reasonable code on the vax using pcc
 */
#define	__sputc(c, p) \
	(--(p)->_w < 0 ? \
		(p)->_w >= (p)->_lbfsize ? \
			(*(p)->_p = (c)), *(p)->_p != '\n' ? \
				(int)*(p)->_p++ : \
				__swbuf('\n', p) : \
			__swbuf((int)(c), p) : \
		(*(p)->_p = (c), (int)*(p)->_p++))
#endif
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris