>From 7ebe34528c241903b3253e8366fe596db0869d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Sat, 10 Apr 2021 16:54:03 +0100 Subject: [PATCH 2/2] ls: cache name width determination This is especially important now for --sort=width, as that can greatly increase how often this expensive quote_name_width() function is called per file. This also helps the default invocation of ls, or specifically the --format={across,vertical} cases (when --width is not set to 0), to avoid two calls to this function per file. Note the only case where we later compute the width, is for --format=commas. That's only done once though, so we leave the computation close to use to maximize hardware caching. * src/ls.c (struct fileinfo): Add a WIDTH member to cache the screen width of the file name. (update_current_files_cache): Set the WIDTH members for cases they're needed multiple times. Note we do this explicitly here, rather than caching at use, so that the fileinfo structures can remain const in the sorting and presentation functions. (sort_files): Call the new update_current_files_cache() in this initialization function. (fileinfo_name_width): Renamed from fileinfo_width, and adjusted to return the cached value if available. --- src/ls.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/ls.c b/src/ls.c index b9fde25d5..b4edf620f 100644 --- a/src/ls.c +++ b/src/ls.c @@ -235,6 +235,9 @@ struct fileinfo /* Whether file name needs quoting. tri-state with -1 == unknown. */ int quoted; + + /* Cached screen width (including quoting). */ + size_t width; }; #define LEN_STR_PAIR(s) sizeof (s) - 1, s @@ -3883,17 +3886,22 @@ cmp_extension (struct fileinfo const *a, struct fileinfo const *b, return diff ? diff : cmp (a->name, b->name); } +/* Return the (cached) screen width, + for the NAME associated with the passed fileinfo F. */ + static inline size_t -fileinfo_width (struct fileinfo const *f) +fileinfo_name_width (struct fileinfo const *f) { - return quote_name_width (f->name, filename_quoting_options, f->quoted); + return f->width + ? f->width + : quote_name_width (f->name, filename_quoting_options, f->quoted); } static inline int cmp_width (struct fileinfo const *a, struct fileinfo const *b, int (*cmp) (char const *, char const *)) { - int diff = fileinfo_width (a) - fileinfo_width (b); + int diff = fileinfo_name_width (a) - fileinfo_name_width (b); return diff ? diff : cmp (a->name, b->name); } @@ -4003,6 +4011,24 @@ initialize_ordering_vector (void) sorted_file[i] = &cwd_file[i]; } +/* Cache values based on attributes global to all files. */ + +static void +update_current_files_cache (void) +{ + size_t i; + + for (i = 0; i < cwd_n_used; i++) + { + struct fileinfo *f = sorted_file[i]; + + /* Cache screen width of name, if needed multiple times. */ + if (sort_type == sort_width + || (line_length && (format == many_per_line || format == horizontal))) + f->width = fileinfo_name_width (f); + } +} + /* Sort the files now in the table. */ static void @@ -4019,6 +4045,8 @@ sort_files (void) initialize_ordering_vector (); + update_current_files_cache (); + if (sort_type == sort_none) return; @@ -5055,7 +5083,7 @@ length_of_file_name_and_frills (const struct fileinfo *f) if (print_scontext) len += 1 + (format == with_commas ? strlen (f->scontext) : scontext_width); - len += quote_name_width (f->name, filename_quoting_options, f->quoted); + len += fileinfo_name_width (f); if (indicator_style != none) { -- 2.26.2