From owner-freebsd-arch@FreeBSD.ORG Sun Mar 6 07:51:50 2005 Return-Path: Delivered-To: freebsd-arch@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id A973116A4CE for ; Sun, 6 Mar 2005 07:51:50 +0000 (GMT) Received: from ylpvm43.prodigy.net (ylpvm43-ext.prodigy.net [207.115.57.74]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2B7D143D39 for ; Sun, 6 Mar 2005 07:51:50 +0000 (GMT) (envelope-from nate@root.org) Received: from [10.0.5.51] (adsl-64-171-186-189.dsl.snfc21.pacbell.net [64.171.186.189])j267pnoo032532 for ; Sun, 6 Mar 2005 02:51:50 -0500 Message-ID: <422AB693.9040600@root.org> Date: Sat, 05 Mar 2005 23:51:47 -0800 From: Nate Lawson User-Agent: Mozilla Thunderbird 1.0RC1 (X11/20041205) X-Accept-Language: en-us, en MIME-Version: 1.0 To: arch@freebsd.org Content-Type: multipart/mixed; boundary="------------030500080703020202000908" Subject: patch: optimize mbnambuf routines in msdosfs X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 06 Mar 2005 07:51:50 -0000 This is a multi-part message in MIME format. --------------030500080703020202000908 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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 --------------030500080703020202000908 Content-Type: text/plain; name="msd2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="msd2.diff" 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 --------------030500080703020202000908--