aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2025-08-04 19:21:45 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2025-08-04 19:21:45 +0200
commita33ce612b5f51446e9d69ec5f41d5e2e2bcb4a84 (patch)
treea07c37043f80e833d61775b1973a5bb947cd71f1 /libbb
parentd7d8ffed87679494be09d710c55dc0b7940e6547 (diff)
downloadbusybox-w32-a33ce612b5f51446e9d69ec5f41d5e2e2bcb4a84.tar.gz
busybox-w32-a33ce612b5f51446e9d69ec5f41d5e2e2bcb4a84.tar.bz2
busybox-w32-a33ce612b5f51446e9d69ec5f41d5e2e2bcb4a84.zip
libbb: much faster concat_path_file()
function old new delta concat_path_file 68 127 +59 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'libbb')
-rw-r--r--libbb/concat_path_file.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/libbb/concat_path_file.c b/libbb/concat_path_file.c
index 5b4b7f113..dec9588ea 100644
--- a/libbb/concat_path_file.c
+++ b/libbb/concat_path_file.c
@@ -17,6 +17,7 @@
17 17
18char* FAST_FUNC concat_path_file(const char *path, const char *filename) 18char* FAST_FUNC concat_path_file(const char *path, const char *filename)
19{ 19{
20#if 0
20 char *lc; 21 char *lc;
21 22
22 if (!path) 23 if (!path)
@@ -25,4 +26,78 @@ char* FAST_FUNC concat_path_file(const char *path, const char *filename)
25 while (*filename == '/') 26 while (*filename == '/')
26 filename++; 27 filename++;
27 return xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename); 28 return xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename);
29#else
30/* ^^^^^^^^^^^ timing of xasprintf-based code above:
31 * real 7.074s
32 * user 0.156s <<<
33 * sys 6.394s
34 * "rm -rf" of a Linux kernel tree from tmpfs (run time still dominated by in-kernel work, though)
35 * real 6.989s
36 * user 0.055s <<< 3 times less CPU used
37 * sys 6.450s
38 * vvvvvvvvvvv timing of open-coded malloc+memcpy code below (+59 bytes):
39 */
40 char *buf, *p;
41 size_t n1, n2, n3;
42
43 while (*filename == '/')
44 filename++;
45
46 if (!path || !path[0])
47 return xstrdup(filename);
48
49 n1 = strlen(path);
50 n2 = (path[n1 - 1] != '/'); /* 1: "path has no trailing slash" */
51 n3 = strlen(filename) + 1;
52
53 buf = xmalloc(n1 + n2 + n3);
54 p = mempcpy(buf, path, n1);
55 if (n2)
56 *p++ = '/';
57 p = mempcpy(p, filename, n3);
58 return buf;
59#endif
60}
61
62/* If second component comes from struct dirent,
63 * it's possible to eliminate one strlen() by using name length
64 * provided by kernel in struct dirent. See below.
65 * However, the win seems to be insignificant.
66 */
67
68#if 0
69
70/* Extract d_namlen from struct dirent */
71static size_t get_d_namlen(const struct dirent *de)
72{
73#if defined(_DIRENT_HAVE_D_NAMLEN)
74 return de->d_namlen;
75#elif defined(_DIRENT_HAVE_D_RECLEN)
76 const size_t prefix_sz = offsetof(struct dirent, d_name);
77 return de->d_reclen - prefix_sz;
78#else
79 return strlen(de->d_name);
80#endif
81}
82
83char* FAST_FUNC concat_path_dirent(const char *path, const struct dirent *de)
84{
85 char *buf, *p;
86 size_t n1, n2, n3;
87
88 if (!path || !path[0])
89 return xstrdup(de->d_name);
90
91 n1 = strlen(path);
92 n2 = (path[n1 - 1] != '/');
93 n3 = get_d_namlen(de) + 1;
94
95 buf = xmalloc(n1 + n2 + n3);
96 p = mempcpy(buf, path, n1);
97 if (n2)
98 *p++ = '/';
99 p = mempcpy(p, de->d_name, n3);
100 return buf;
28} 101}
102
103#endif