Skip site navigation (1) Skip section navigation (2)

Peripheral Links

Header And Logo

PostgreSQL
| The world's most advanced open source database.

Site Navigation

Search archives
  Advanced Search

performance: use pread instead of lseek+read


  • From: Manfred Spraul <manfred(at)colorfullife(dot)com>
  • To: pgsql-patches(at)postgresql(dot)org
  • Subject: performance: use pread instead of lseek+read
  • Date: Mon, 24 Feb 2003 19:24:09 +0100
  • Message-id: <3E5A6349.4060900@colorfullife.com> <text/plain>

Hi all,

postgresql tries very hard to avoid calling lseek if not needed, probably to avoid doing unnecessary syscalls.
What about removing lseek entirely and using the p{read,write}?

pread is identical to the normal read syscall, except that it has one additional parameter: the position from which the data should be read.
All recent unices support that, it's part of POSIX.1c.

Attached is a patch vs the cvs tree.
It seems to work - 7.3.2 with the patch applied passes the regression test suite on RH Linux.
Untested with cvs-head, preproc.y causes a parser overflow.

What do you think?
- configure: I test for existance of pread, and assume that pwrite will exist, too. Acceptable? - Are you interested in further patches? xlog.c contains a few lseeks, but I doubt that they are in the critical path.

--
  Manfred
diff -u -u -r -x configure pgsql.orig/configure.in pgsql/configure.in
--- pgsql.orig/configure.in	2003-02-19 05:04:04.000000000 +0100
+++ pgsql/configure.in	2003-02-23 09:38:46.000000000 +0100
@@ -786,7 +786,7 @@
 # SunOS doesn't handle negative byte comparisons properly with +/- return
 AC_FUNC_MEMCMP
 
-AC_CHECK_FUNCS([cbrt fcvt getpeereid memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync utime utimes])
+AC_CHECK_FUNCS([cbrt fcvt getpeereid memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen fdatasync utime utimes pread])
 
 AC_CHECK_DECLS(fdatasync, [], [], [#include <unistd.h>])
 
diff -u -u -r -x configure pgsql.orig/src/backend/storage/file/fd.c pgsql/src/backend/storage/file/fd.c
--- pgsql.orig/src/backend/storage/file/fd.c	2002-09-02 08:11:42.000000000 +0200
+++ pgsql/src/backend/storage/file/fd.c	2003-02-23 09:45:41.000000000 +0100
@@ -391,7 +391,9 @@
 	Delete(file);
 
 	/* save the seek position */
+#ifndef HAVE_PREAD
 	vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR);
+#endif
 	Assert(vfdP->seekPos != -1L);
 
 	/* close the file */
@@ -462,6 +464,7 @@
 			++nfile;
 		}
 
+#ifndef HAVE_PREAD
 		/* seek to the right position */
 		if (vfdP->seekPos != 0L)
 		{
@@ -470,6 +473,7 @@
 			returnValue = (long) lseek(vfdP->fd, vfdP->seekPos, SEEK_SET);
 			Assert(returnValue != -1L);
 		}
+#endif
 	}
 
 	/*
@@ -877,11 +881,17 @@
 			   VfdCache[file].seekPos, amount, buffer));
 
 	FileAccess(file);
+#if HAVE_PREAD
+	returnCode = pread(VfdCache[file].fd, buffer, amount, VfdCache[file].seekPos);
+	if (returnCode > 0)
+		VfdCache[file].seekPos += returnCode;
+#else
 	returnCode = read(VfdCache[file].fd, buffer, amount);
 	if (returnCode > 0)
 		VfdCache[file].seekPos += returnCode;
 	else
 		VfdCache[file].seekPos = FileUnknownPos;
+#endif
 
 	return returnCode;
 }
@@ -900,16 +910,25 @@
 	FileAccess(file);
 
 	errno = 0;
+#if HAVE_PREAD
+	returnCode = pwrite(VfdCache[file].fd, buffer, amount, VfdCache[file].seekPos);
+#else
 	returnCode = write(VfdCache[file].fd, buffer, amount);
+#endif
 
 	/* if write didn't set errno, assume problem is no disk space */
 	if (returnCode != amount && errno == 0)
 		errno = ENOSPC;
 
+#if HAVE_PREAD
+	if (returnCode > 0)
+		VfdCache[file].seekPos += returnCode;
+#else
 	if (returnCode > 0)
 		VfdCache[file].seekPos += returnCode;
 	else
 		VfdCache[file].seekPos = FileUnknownPos;
+#endif
 
 	return returnCode;
 }
@@ -951,12 +970,20 @@
 			case SEEK_SET:
 				if (offset < 0)
 					elog(ERROR, "FileSeek: invalid offset: %ld", offset);
+#ifdef HAVE_PREAD
+				VfdCache[file].seekPos = offset;
+#else
 				if (VfdCache[file].seekPos != offset)
 					VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
+#endif
 				break;
 			case SEEK_CUR:
+#ifdef HAVE_PREAD
+				VfdCache[file].seekPos += offset;
+#else
 				if (offset != 0 || VfdCache[file].seekPos == FileUnknownPos)
 					VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
+#endif
 				break;
 			case SEEK_END:
 				VfdCache[file].seekPos = lseek(VfdCache[file].fd, offset, whence);
diff -u -u -r -x configure pgsql.orig/src/include/pg_config.h.in pgsql/src/include/pg_config.h.in
--- pgsql.orig/src/include/pg_config.h.in	2003-02-19 05:04:04.000000000 +0100
+++ pgsql/src/include/pg_config.h.in	2003-02-23 09:59:47.000000000 +0100
@@ -544,6 +544,9 @@
 /* Define if the standard header unistd.h declares fdatasync() */
 #undef HAVE_DECL_FDATASYNC
 
+/* Define if you have pread(). Implies pwrite, too. */
+#undef HAVE_PREAD
+
 /* Set to 1 if you have libz.a */
 #undef HAVE_LIBZ
 


Home | Main Index | Thread Index

Privacy Policy | About PostgreSQL
Copyright © 1996 – 2012 PostgreSQL Global Development Group