unix: optimize uv_fs_readlink() memory allocation

Libuv was allocating PATH_MAX+1 bytes to reserve space for the trailing
nul byte.

On platforms like Linux, where PATH_MAX is fixed at 4096, that meant we
were allocating two pages (as the page size is normally also 4096), even
though the second page was almost never used.

Change that to allocate PATH_MAX bytes and only resize when readlink()
actually writes that many bytes, which is practically never.

PR-URL: https://github.com/libuv/libuv/pull/2009
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
Ben Noordhuis 2018-10-08 11:51:26 +02:00
parent 3af6f17241
commit 5ecc97ee7d

View File

@ -388,11 +388,13 @@ static ssize_t uv__fs_pathmax_size(const char* path) {
}
static ssize_t uv__fs_readlink(uv_fs_t* req) {
ssize_t maxlen;
ssize_t len;
char* buf;
char* newbuf;
len = uv__fs_pathmax_size(req->path);
buf = uv__malloc(len + 1);
maxlen = uv__fs_pathmax_size(req->path);
buf = uv__malloc(maxlen);
if (buf == NULL) {
errno = ENOMEM;
@ -400,17 +402,28 @@ static ssize_t uv__fs_readlink(uv_fs_t* req) {
}
#if defined(__MVS__)
len = os390_readlink(req->path, buf, len);
len = os390_readlink(req->path, buf, maxlen);
#else
len = readlink(req->path, buf, len);
len = readlink(req->path, buf, maxlen);
#endif
if (len == -1) {
uv__free(buf);
return -1;
}
/* Uncommon case: resize to make room for the trailing nul byte. */
if (len == maxlen) {
newbuf = uv__realloc(buf, len + 1);
if (newbuf == NULL) {
uv__free(buf);
return -1;
}
buf = newbuf;
}
buf[len] = '\0';
req->ptr = buf;