some benchmark data for fsync (2.3.19, 2.3.19+fastsync, NT)

Martin Schenk (martin@ping.at)
Thu, 07 Oct 1999 22:11:31 +0200


This is a multi-part message in MIME format.
--------------E777138EE724D9063B545374
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Here are some benchmark data to show the difference my fastsync patch
(posted here a few days ago as "faster fsync and real fdatasync") can
make.

Basically this patch omits a scan through all the cached blocks of a
file
on fsync and it enables fdatasync not to sync the inode if only
mtime/ctime
are changed.

The following data has been generated on a dual PIII-450 with 128Mbyte
memory
(IBM-DJNA-351520 ide hard disk ~9msec, write cache on disk
***disabled***)

The test creates a file and then does 1000 individual writes in the
file,
syncing after every write.

blocks (2Kb each) 2.3.19 2.3.19+fastsync NT
--------------------------------------------------------
5000 28 17 37
50000 137 27 42
5000 (fdatasync) 0.2-9
50000(fdatasync) 3-9

2.3.19 takes about 30% CPU at 5000, >80% at 50000 blocks, the others
don't
take significant CPU time.
With 2.3.19+fastsync, the time corresponds to 2 seeks (one to the inode,
one
to the data) in the fsync case (the distance is bigger in the bigger
file).
The time in the fdatasync case depends a lot on the actual place of the
file
on disk (as there is only a seek from data to data). With the smaller
file,
you need almost no arm movements if you are lucky :-)
[ if your times are a lot lower and fdatasync makes no difference, try
to
disable hard disk write caching (on a production system you should do it
anyway, unless you have same special battery cached RAID)]

btw: I assume NTFS is slower because it needs to commit its metadata -
does
anybody know whether there is a fdatasync equivalent on NT ?

What are the real-world effects of this ?

>From what I wrote above, it is easy to see that the "bigger" your
hardware,
the more the normal fsync slows you down (Anybody who wants to measure
how
long this benchmark takes on a machine with 1gb ram and a 1gb file ?)
and
as fsync takes the global kernel_lock for a very long time, additional
CPUs
are very likely to spin on it.

It would be very interesting to see the difference my patch makes to
a real life database application (especially if it is doing a lot of
small
transactions) [on a SMP system you can use the spinlock metering patch
from sgi to see how long sys_fsync/sys_fdatasync holds your CPU(s)]

I'm very interested in feedback. Please tell me what I have to change in
my patch so that it gets acceptable for inclusion in 2.4
[I consider this a bug-fix not an additional feature]

I attached the source code for the small benchmark program, it should
compile
on Linux and NT. You should find the fastsync patch in the linux-kernel
archives (I sent it during the night from Oct 04 to Oct 05), or mail me
for it.
--------------E777138EE724D9063B545374
Content-Type: text/plain; charset=us-ascii;
name="synctest.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="synctest.c"

#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32
#include <unistd.h>
#include <sys/time.h>
#endif
#include <fcntl.h>

#ifdef _WIN32
#include <windows.h>
#include <io.h>
#include <memory.h>
#define fsync _commit
#define fdatasync _commit
#endif

int main(int argc, char **argv)
{
#ifndef _WIN32
struct timeval tv;
#endif
double t;
double xt;
int fd,i;
char buff[2048];
int size;
int step;
int fastsync=0;
int fcnt=0;

if (argc>2) { fastsync=1; printf("fastsync\n"); }
size=atoi(argv[1]);
if (size<1000) exit(1);
step=((size/1000)-1)*2048;
printf("step: %d\n", step);

fd=open("tst", O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd<0) exit(1);

memset(buff, 0, 2048);
printf("init \n");
for (i=0; i<size; i++)
{
write(fd, buff, 2048);
}
fsync(fd);
memset(buff, 1, 2048);
printf("sync\n");
lseek(fd, 0, SEEK_SET);
#ifndef _WIN32
gettimeofday(&tv, NULL);
xt=t=(double)tv.tv_sec+(double)tv.tv_usec/1000000.0;
#else
xt=t=(double)GetTickCount()/1000.0;
#endif
for (i=0; i<1000; i++)
{
double nt;
if (step>1)
if (lseek(fd, step, SEEK_CUR)<0) printf("lseek ???\n");
if (write(fd, buff, 2048)<0) printf("write ???\n");
if (fastsync) fdatasync(fd);
else fsync(fd);
#ifndef _WIN32
gettimeofday(&tv, NULL);
nt=((double)tv.tv_sec+(double)tv.tv_usec/1000000.0);
#else
nt=(double)GetTickCount()/1000.0;
#endif
if ((nt-xt)<0.0001) printf("%f: too fast ? (%d)\n", nt-xt, ++fcnt);
xt=nt;
}
#ifndef _WIN32
gettimeofday(&tv, NULL);
t=((double)tv.tv_sec+(double)tv.tv_usec/1000000.0)-t;
#else
t=((double)GetTickCount()/1000.0)-t;
#endif
printf("time: %f\n", t);
close(fd);
}

--------------E777138EE724D9063B545374--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/