patch: optimize mbnambuf routines in msdosfs

From: Nate Lawson (nate_at_root.org)
Date: 03/06/05

  • Next message: Ryan Sommers: "Re: patch: clean up msdosfs conversion routine"
    Date: Sat, 05 Mar 2005 23:51:47 -0800
    To: arch@freebsd.org
    
    
    

    In my profiling, I found mbnambuf_* were the top 4 CPU hogs on my system
    when doing directory IO on an msdosfs partition. After examination, no
    wonder: repeated malloc/free, excessive strcpy, etc.

    The mbnambuf is indexed by the windows ID, a sequential one-based value.
        The attached patch optimizes this routine with this in mind, using
    the ID to index into a single array and concatenating each WIN_CHARS
    chunk at once. (The last chunk is variable-length.)

    The part I'd like review for especially is the struct dirent semantics.
      The sys/dirent.h says that the names should always be null-terminated
    to a multiple of 4 bytes. The original code did not do this and neither
    does mine. (It always null terminates, but the result can be an odd
    number of bytes long.)

    This code has been tested as working on an FS with dificult filename
    sizes (255, 13, 26, etc.) It gives a whopping 77.1% decrease in
    profiled time (total across all functions) and a 73.7% decrease in wall
    time. Test was "ls -laR > /dev/null"

    Individual performance gains are below:
    mbnambuf_init: -90.7%
    mbnambuf_write: -18.7%
    mbnambuf_flush: -67.1%

    -- 
    Nate
    
    

    Index: msdosfs_conv.c
    ===================================================================
    RCS file: /home/ncvs/src/sys/fs/msdosfs/msdosfs_conv.c,v
    retrieving revision 1.39
    diff -u -r1.39 msdosfs_conv.c
    --- msdosfs_conv.c 8 Feb 2005 07:51:14 -0000 1.39
    +++ msdosfs_conv.c 2 Mar 2005 17:48:52 -0000
    @@ -101,11 +102,13 @@
     static u_int16_t win2unixchr(u_int16_t, struct msdosfsmount *);
     static u_int16_t unix2winchr(const u_char **, size_t *, int, struct msdosfsmount *);
     
    +#if 0
     struct mbnambuf {
             char * p;
             size_t n;
     };
     static struct mbnambuf subent[WIN_MAXSUBENTRIES];
    +#endif
     
     /*
      * Convert the unix version of time to dos's idea of time to be used in
    @@ -1194,6 +1198,7 @@
             return (wc);
     }
     
    +#if 0
     /*
      * Make subent empty
      */
    @@ -1251,3 +1257,55 @@
             mbnambuf_init();
             return (dp->d_name);
     }
    +#else
    +
    +static char *nambuf_ptr;
    +static size_t nambuf_len;
    +static int nambuf_max_id;
    +
    +void
    +mbnambuf_init(void)
    +{
    +
    + if (nambuf_ptr == NULL) {
    + nambuf_ptr = malloc(MAXNAMLEN + 1, M_MSDOSFSMNT, M_WAITOK);
    + nambuf_ptr[MAXNAMLEN] = '\0';
    + }
    + nambuf_len = 0;
    + nambuf_max_id = -1;
    +}
    +
    +void
    +mbnambuf_write(char *name, int id)
    +{
    + size_t count;
    +
    + count = WIN_CHARS;
    + if (id > nambuf_max_id) {
    + count = strlen(name);
    + nambuf_len = id * WIN_CHARS + count;
    + if (nambuf_len > MAXNAMLEN) {
    + printf("msdosfs: file name %d too long\n", nambuf_len);
    + return;
    + }
    + nambuf_max_id = id;
    + }
    + memcpy(nambuf_ptr + (id * WIN_CHARS), name, count);
    +}
    +
    +char *
    +mbnambuf_flush(struct dirent *dp)
    +{
    +
    + if (nambuf_len > sizeof(dp->d_name) - 1) {
    + mbnambuf_init();
    + return (NULL);
    + }
    + nambuf_ptr[nambuf_len] = '\0';
    + memcpy(dp->d_name, nambuf_ptr, nambuf_len + 1);
    + dp->d_namlen = nambuf_len;
    +
    + mbnambuf_init();
    + return (dp->d_name);
    +}
    +#endif

    
    

    _______________________________________________
    freebsd-arch@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-arch
    To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"


  • Next message: Ryan Sommers: "Re: patch: clean up msdosfs conversion routine"