I was wondering why strlen() showed up over 3M times when
running "rm -rf some-dir" - where "some-dir" contained 1M files.
This was shown by "ltrace -c ...".

The attached avoids 2M strlen() invocations for this case.

Sorry that the patch is in an attachment, but "git send-email"
does not work on the box I was on.

Have a nice day,
Berny

>From 8f34e10691c91b20d71f128af1ee2f66b57e6183 Mon Sep 17 00:00:00 2001
From: Bernhard Voelker <[email protected]>
Date: Wed, 9 Apr 2014 14:14:08 +0200
Subject: [PATCH] fts: avoid unnecessary strlen calls

* lib/fts.c (_D_EXACT_NAMLEN): Remove macro.
(fts_build): Store the length of the dp->d_name entry in a local variable
instead of calling strlen() several times via the above, removed macro.
For 'rm -rf some-dir' with e.g. 1M directory entries, this speeds up the
run by ~4%, yet this reduces the execution time by about a third if run
via "ltrace -c rm -rf some-dir".
---
 ChangeLog | 10 ++++++++++
 lib/fts.c | 14 ++++++--------
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0d0ac9e..0e9a383 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2014-03-26  Bernhard Voelker  <[email protected]>
+
+	fts: avoid unnecessary strlen calls
+	* lib/fts.c (_D_EXACT_NAMLEN): Remove macro.
+	(fts_build): Store the length of the dp->d_name entry in a local variable
+	instead of calling strlen() several times via the above, removed macro.
+	For 'rm -rf some-dir' with e.g. 1M directory entries, this speeds up the
+	run by ~4%, yet this reduces the execution time by about a third if run
+	via "ltrace -c rm -rf some-dir".
+
 2014-03-27  Paul Eggert  <[email protected]>
 
 	obstack: Remove ancient NeXTSTEP gcc support conditional
diff --git a/lib/fts.c b/lib/fts.c
index bc3c3c1..592fe58 100644
--- a/lib/fts.c
+++ b/lib/fts.c
@@ -79,9 +79,6 @@ static char sccsid[] = "@(#)fts.c       8.6 (Berkeley) 8/14/94";
 #endif
 
 #include <dirent.h>
-#ifndef _D_EXACT_NAMLEN
-# define _D_EXACT_NAMLEN(dirent) strlen ((dirent)->d_name)
-#endif
 
 #if HAVE_STRUCT_DIRENT_D_TYPE
 /* True if the type of the directory entry D is known.  */
@@ -1447,19 +1444,20 @@ fts_build (register FTS *sp, int type)
         nitems = 0;
         while (cur->fts_dirp) {
                 bool is_dir;
+                size_t namlen;
                 struct dirent *dp = readdir(cur->fts_dirp);
                 if (dp == NULL)
                         break;
                 if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
                         continue;
 
-                if ((p = fts_alloc (sp, dp->d_name,
-                                    _D_EXACT_NAMLEN (dp))) == NULL)
+                namlen = strlen (dp->d_name);
+                if ((p = fts_alloc (sp, dp->d_name, namlen)) == NULL)
                         goto mem1;
-                if (_D_EXACT_NAMLEN (dp) >= maxlen) {
+                if (namlen >= maxlen) {
                         /* include space for NUL */
                         oldaddr = sp->fts_path;
-                        if (! fts_palloc(sp, _D_EXACT_NAMLEN (dp) + len + 1)) {
+                        if (! fts_palloc(sp, namlen + len + 1)) {
                                 /*
                                  * No more memory.  Save
                                  * errno, free up the current structure and the
@@ -1483,7 +1481,7 @@ mem1:                           saved_errno = errno;
                         maxlen = sp->fts_pathlen - len;
                 }
 
-                new_len = len + _D_EXACT_NAMLEN (dp);
+                new_len = len + namlen;
                 if (new_len < len) {
                         /*
                          * In the unlikely event that we would end up
-- 
1.8.4.2

Reply via email to