[nylug-talk] questions about /dev/null

Peter C. Norton spacey-nylug at lenin.net
Mon Nov 5 10:56:46 EST 2007


On Mon, Nov 05, 2007 at 07:30:29AM -0400, Sunny Dubey wrote:
> On Monday 05 November 2007 02:04:03 am Judd Maltin wrote:
> > Is there any reason writing a stream of ASCII to /dev/null would be
> > faster than copying the same file to /dev/null ?
> >
> > And then int he context of MySQL, why would it be faster to do a
> > mysqldump into /dev/null than to do a mysqlhotcopy into /dev/null -
> > faster by 1/2 the time.
> >
> > Odd, odd. ?Is it inodes? ?For some reason not reading smoothly across
> > the disk?
> 
> This is a common misconception.
> 
> /dev/null is a *file*.  It is a special file and not a regular one:
> 
> sunny at localhost ~ $ file /dev/null
> /dev/null: character special (1/3)

Yes, and as such it still has inodes, etc.
 
> Writing *TO* /dev/null causes no disk activity because you are writing to a 
> file that simply discards the information.  Writing *ON* /dev/null causes 
> disk activity because now you have replaced the file with something else that 
> does not discard the information, and actually grows with whatever you are 
> writing on it.

I'm not sure you're on the right track here.  A regular user can't
unlink and overwrite /dev/null, which is always owned by root in a
directory that is owned by root and is not world-writeable. This means
that the directory entry can't be removed and subsequently replaced by
a normal user. Even in the root user case, the open() system call will
open an existing file. It will not unlink() and then create a new
file. I think the answer is a bit different...

> You can think of /dev/null as a garbage pail with a bottomless pit.  You could 
> throw everything at it, and it would simply "disappear".  But the moment you 
> replace it with not something special, a garbage mound would start to grow.

This usually can't happen (if it ever does happen on a system, it's
probably by some combination of deliberate and stupid and malicious),
and many, many things would break once the filesystem under /dev
filled up.

The usual reason for writes to /dev/null happening faster with some
programs and scripts than with others is that the C library or the
system may treat /dev/null very specially. If it knows that it's
supposed to write to the null device, it will probably short-circuit
the process and simply free the memory that would have been written.

*However* when a program has to write to a pipe or to stdout/stderr
which *then* gets dumped to /dev/null, then the program has to first
do the write, and the reading end of the pipe has to read, and errors
checked, etc.

Something I did recently showed this off:

First, prime the read-cache:

spacey at spacey:~$ sudo dd if=/dev/md0 of=/dev/null bs=1024k count=100
Password:
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 1.81393 seconds, 57.8 MB/s

Second, re-run with the same space in cache:

spacey at spacey:~$ sudo dd if=/dev/md0 of=/dev/null bs=1024k
count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.579875 seconds, 181 MB/s

Run again, this time with ">", which still gives the process a file
descriptor that leads to /dev/null:

spacey at spacey:~$ sudo dd if=/dev/md0  bs=1024k count=100 >
/dev/null
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.577291 seconds, 182 MB/s

Now watch what happens when we put a process in the middle, even a
stupid process, that has to read the pipe before throwing out the
data:

spacey at spacey:~$ sudo dd if=/dev/md0  bs=1024k count=100 | cat >
/dev/null
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 1.79849 seconds, 58.3 MB/s

To show it's not a fluke:

spacey at spacey:~$ sudo dd if=/dev/md0  bs=1024k count=100 | cat >
/dev/null
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 1.72081 seconds, 60.9 MB/s

So that's the slowdown for a simple, simple, simple program like "cat"
to read buffere stdin and to throw it out. A >50% slowdown. The kernel
or the C library simply has to stat() the file being written to, and
see if it matches the st_rdev of /dev/null on the current system (yes,
it's not codified anywhere that these device numbers must be uniform
across platforms or releases).

Disclaimer: no /dev/nulls were harmed during the filming of this
demonstration.

-Peter

P.S. This is a common optimization on all unix platforms that I'm
aware of.

-- 
The 5 year plan:
In five years we'll make up another plan.
Or just re-use this one.



More information about the nylug-talk mailing list