Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 06 Oct 2002 22:28:27 +0200
From:      Poul-Henning Kamp <phk@freebsd.org>
To:        current@freebsd.org
Subject:   GEOM benchmarks
Message-ID:  <81529.1033936107@critter.freebsd.dk>

next in thread | raw e-mail | index | archive | help

A number of people have asked me for performance data on GEOM
already, so here are up-to-the-minute relevant numbers:

On my test machine (see the details below), a 512 bytes read
from the initialized first sector on a malloc-backed md(4)
device takes 21.7 microsecond, for both "mdX", "mdXs1"
and "mdXs1c".

GEOM is stacked, so there the times depend on the number
of layers we have to go through:

	device	time		  layers
	---------------------------------------------
	mdX     26.8 microsecond  dev, disk
	mdXs1   27.1 microsecond  dev, mbr, disk
	mdXs1c  28.4 microsecond  dev, bsd, mbr, disk

So roughly speaking, GEOM itself costs 5 microseconds per
I/O transaction and each simple geom_slicer.c based disk
geometry adds about 800nsec to that.

The transfersize does not matter in this, since geom does
not touch the actual data for the common geom_slicer.c
method.

The same read operation takes 3.6 microsecond on /dev/zero.

Now, I will agree that for md(4) with a malloc backing, this is a
very big slowdown: it takes 23% longer time, but on a regular
disk 5 microseconds is totally lost in the noise.

Some words of caution, to anyone who want to benchmark this
themselves:

With GEOM, a part of the overhead is charged against the GEOM
kernel threads, and the regular "resource" printout by time(1)
or similar will not account for this part of the actual CPU
usage, so if you compare GEOM to NO_GEOM worldstone, it is not
unexpected that the "system" time may actually drop, despite
the measurements I presented above.

It is also worth knowing that GEOM is a Giant-free zone.  This means
that using GEOM opens up a window for parallelism in the middle of
the I/O path which were not previously there which means that things
may be able to arrange themselves in a different pattern.

Poul-Henning

-----------------------------------------------------------------------

The test-setup is a 1-CPU 700MHz Athlon system booted diskless on
-current kernel from this morning with no WITNESS or KTRACE, and
with no other disk activity in the system.

The test-disk is a 1 megabyte malloc backed md(4) device initialized
with 
	fdisk -I mdX
	disklabel -r -w auto mdXs1

The test program (attached below) basically runs 100,000 loops
like this:
        for(j = 0;j < N; j++) {
                lseek(0, SEEK_SET, 0);
                i = read(0, buf, 512);
                if (i != 512)
                        exit(2);
        }
with stdin pointed at the target device by the shell.
The program outputs the number of nanoseconds per iteration of
the loop.

The testprogram is then run 10 times for each of the following
devices: /dev/zero, /dev/mdX, /dev/mdXs1, /dev/mdXs1c and the average
and standard deviation of the time output is calculated.

The raw data is included below.

-----------------------------------------------------------------------

GEOM:
zero   Samples: 10    Average:  3563.810900   Stddev:  43.855366
md9    Samples: 10    Average: 26773.133200   Stddev: 342.152442
md9s1  Samples: 10    Average: 27077.471800   Stddev: 646.937932
md9s1c Samples: 10    Average: 28436.273300   Stddev: 209.271601

NO_GEOM:
zero   Samples: 10    Average:  3741.171000   Stddev:  26.748924
md9    Samples: 10    Average: 21752.482800   Stddev: 181.397713
md9s1  Samples: 10    Average: 21643.089000   Stddev: 204.512877
md9s1c Samples: 10    Average: 21639.226900   Stddev: 158.514456

-----------------------------------------------------------------------

/* tst.c */
#include <sys/time.h>
    
#define N 100000
char buf[512];
main()
{
        int i, j;
        int c, z;
        double a;
        struct timeval t1, t2;

        for(j = 0;j < 100; j++) {
                lseek(0, SEEK_SET, 0);
                i = read(0, buf, 512);
                if (i != 512)
                        exit(2); 
        }
        gettimeofday(&t1, NULL);
        for(j = 0;j < N; j++) {
                lseek(0, SEEK_SET, 0);
                i = read(0, buf, 512);
                if (i != 512)
                        exit(2);
        }
        gettimeofday(&t2, NULL);
        a =  t2.tv_sec + t2.tv_usec / 1e6;
        a -= t1.tv_sec + t1.tv_usec / 1e6;
        printf("%.3f\n", (a / N) * 1e9 );
        exit (0);
}

-- 
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD committer       | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?81529.1033936107>