On Sat Nov 19 11, Tim Kientzle wrote:
> 
> On Nov 18, 2011, at 12:31 PM, Alexander Best wrote:
> 
> > On Fri Nov 18 11, Tim Kientzle wrote:
> >> 
> >> Take a look at 
> >> 
> >> http://libarchive.googlecode.com/svn/trunk/libarchive/archive_read_open_filename.c
> >> 
> >> Especially the comments about detecting "disk-like" devices.
> >> I rewrote a bunch of this code to introduce an explicit
> >> notion of "strategy" so that we could optimize access
> >> to a variety of different devices.
> >> 
> >> This code has a notion of "disk-like" file descriptors and
> >> some optimizations for such.  There are some comments
> >> in there outlining similar optimizations that could be made
> >> for "tape-like" or "socket-like" devices.
> > 
> > great you posted that file as reference. i believe most of the stuff done 
> > there
> > should actually be done within lseek().
> 
> Libarchive runs on a lot of systems other than FreeBSD.
> FreeBSD is not the only Unix-like system with this issue,
> so that code isn't going to go out of libarchive regardless.
> 
> If you think those same ideas can be used in dd or hd
> to speed them up, please send your patches.

i'd like to propose the followup patch for hexdump(1). basically,
the logic behind is is this:

1) if the file argument is a fifo, pipe or socket   --  goto 4)
2) if the file argument is a tape drive             --  goto 4)
3) for all other cases try fseeko(), if that fails  --  goto 4)

4) use getchar()

you should notice a dramtic increase in speed from something like the
following:

'hexdump -s 500m -n32 /dev/random'

cheers.
alex

> 
> The key point:  You cannot unconditionally call lseek()
> to skip over data.  Instead, treat lseek() as an optimization
> that can be used under some circumstances.  The
> question then becomes one of figuring out when
> that optimization can be enabled.
> 
> Tim
> 
diff --git a/usr.bin/hexdump/display.c b/usr.bin/hexdump/display.c
index 991509d..8c8b065 100644
--- a/usr.bin/hexdump/display.c
+++ b/usr.bin/hexdump/display.c
@@ -35,8 +35,10 @@ static char sccsid[] = "@(#)display.c        8.1 (Berkeley) 
6/6/93";
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/ioctl.h>
 #include <sys/param.h>
 #include <sys/stat.h>
+#include <sys/conf.h>
 
 #include <ctype.h>
 #include <err.h>
@@ -368,7 +370,7 @@ next(char **argv)
 void
 doskip(const char *fname, int statok)
 {
-       int cnt;
+       int type;
        struct stat sb;
 
        if (statok) {
@@ -380,16 +382,38 @@ doskip(const char *fname, int statok)
                        return;
                }
        }
-       if (S_ISREG(sb.st_mode)) {
-               if (fseeko(stdin, skip, SEEK_SET))
+       if (S_ISFIFO(sb.st_mode) || S_ISSOCK(sb.st_mode)) {
+               noseek();
+               return;
+       }
+       if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) {
+               if (ioctl(fileno(stdin), FIODTYPE, &type))
                        err(1, "%s", fname);
-               address += skip;
-               skip = 0;
-       } else {
-               for (cnt = 0; cnt < skip; ++cnt)
-                       if (getchar() == EOF)
-                               break;
-               address += cnt;
-               skip -= cnt;
+               /*
+                * Most tape drives don't support seeking,
+                * yet fseeko() would succeed.
+                */
+               if (type & D_TAPE) {
+                       noseek();
+                       return;
+               }
+        }
+       if (fseeko(stdin, skip, SEEK_SET)) {
+               noseek();
+               return;
        }
+       address += skip;
+       skip = 0;
+}
+
+void
+noseek(void)
+{
+       int count;
+
+       for (count = 0; count < skip; ++count)
+               if (getchar() == EOF)
+                       break;
+       address += count;
+       skip -= count;
 }
diff --git a/usr.bin/hexdump/hexdump.h b/usr.bin/hexdump/hexdump.h
index be85bd9..1d4bb85 100644
--- a/usr.bin/hexdump/hexdump.h
+++ b/usr.bin/hexdump/hexdump.h
@@ -97,6 +97,7 @@ u_char        *get(void);
 void    newsyntax(int, char ***);
 int     next(char **);
 void    nomem(void);
+void    noseek(void);
 void    oldsyntax(int, char ***);
 size_t  peek(u_char *, size_t);
 void    rewrite(FS *);
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to