diff options
| author | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-04 19:21:45 +0200 |
|---|---|---|
| committer | Denys Vlasenko <vda.linux@googlemail.com> | 2025-08-04 19:21:45 +0200 |
| commit | a33ce612b5f51446e9d69ec5f41d5e2e2bcb4a84 (patch) | |
| tree | a07c37043f80e833d61775b1973a5bb947cd71f1 /libbb | |
| parent | d7d8ffed87679494be09d710c55dc0b7940e6547 (diff) | |
| download | busybox-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.c | 75 |
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 | ||
| 18 | char* FAST_FUNC concat_path_file(const char *path, const char *filename) | 18 | char* 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 */ | ||
| 71 | static 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 | |||
| 83 | char* 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 | ||
