perf(os/env): os_getenv() allocation when there is no env var set

os_getenv("FOO") caches the result when $FOO is set to something
non-empty. However, when $FOO was not set, every new call to
os_getenv("FOO") would allocate a temporary scratch buffer to
immediately throw away.

This has an huge impact e.g. on logging which depends on potentially
non-set env vars.
This commit is contained in:
bfredl 2024-02-21 10:49:05 +01:00
parent 15f7ac6a04
commit c5990f2cdc

View File

@ -61,8 +61,7 @@ static PMap(cstr_t) envmap = MAP_INIT;
const char *os_getenv(const char *name) const char *os_getenv(const char *name)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_ALL
{ {
char *e; char *e = NULL;
size_t size = 64;
if (name[0] == '\0') { if (name[0] == '\0') {
return NULL; return NULL;
} }
@ -78,23 +77,31 @@ const char *os_getenv(const char *name)
} }
pmap_del2(&envmap, name); pmap_del2(&envmap, name);
} }
#define INIT_SIZE 64
size_t size = INIT_SIZE;
char buf[INIT_SIZE];
r = uv_os_getenv(name, buf, &size);
if (r == UV_ENOBUFS) {
e = xmalloc(size); e = xmalloc(size);
r = uv_os_getenv(name, e, &size); r = uv_os_getenv(name, e, &size);
if (r == UV_ENOBUFS) {
e = xrealloc(e, size);
r = uv_os_getenv(name, e, &size);
}
if (r != 0 || size == 0 || e[0] == '\0') { if (r != 0 || size == 0 || e[0] == '\0') {
xfree(e); XFREE_CLEAR(e);
goto end;
}
} else if (r != 0 || size == 0 || buf[0] == '\0') {
e = NULL; e = NULL;
goto end; goto end;
} else {
// NB: `size` param of uv_os_getenv() includes the NUL-terminator,
// except when it does not include the NUL-terminator.
e = xmemdupz(buf, size);
} }
pmap_put(cstr_t)(&envmap, xstrdup(name), e); pmap_put(cstr_t)(&envmap, xstrdup(name), e);
end: end:
if (r != 0 && r != UV_ENOENT && r != UV_UNKNOWN) { if (r != 0 && r != UV_ENOENT && r != UV_UNKNOWN) {
ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r)); ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r));
} }
return (e == NULL || size == 0 || e[0] == '\0') ? NULL : e; return e;
} }
/// Returns true if environment variable `name` is defined (even if empty). /// Returns true if environment variable `name` is defined (even if empty).