From 5ecc97ee7d5724982d0bf605dcbb009a572110da Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 8 Oct 2018 11:51:26 +0200 Subject: [PATCH] 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 Reviewed-By: Santiago Gimeno --- src/unix/fs.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index 35bcc6f66..a0c05e18f 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -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;