From 557a6e78256144beb95a175e2d8a7106b01d16c9 Mon Sep 17 00:00:00 2001 From: "L. Pereira" Date: Sat, 24 Aug 2024 16:27:29 -0700 Subject: [PATCH] Use mincore(2) to queue an madvise(2) call if necessary --- CMakeLists.txt | 1 + src/cmake/lwan-build-config.h.cmake | 1 + src/lib/lwan-mod-serve-files.c | 31 ++++++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1e913a75..461b18742 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -175,6 +175,7 @@ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) check_function_exists(get_current_dir_name LWAN_HAVE_GET_CURRENT_DIR_NAME) check_symbol_exists(reallocarray stdlib.h LWAN_HAVE_REALLOCARRAY) check_symbol_exists(eventfd sys/eventfd.h LWAN_HAVE_EVENTFD) +check_symbol_exists(mincore sys/mman.h LWAN_HAVE_MINCORE) check_function_exists(mempcpy LWAN_HAVE_MEMPCPY) check_function_exists(memrchr LWAN_HAVE_MEMRCHR) check_function_exists(pipe2 LWAN_HAVE_PIPE2) diff --git a/src/cmake/lwan-build-config.h.cmake b/src/cmake/lwan-build-config.h.cmake index 6b50d454f..7cf31ab5f 100644 --- a/src/cmake/lwan-build-config.h.cmake +++ b/src/cmake/lwan-build-config.h.cmake @@ -49,6 +49,7 @@ #cmakedefine LWAN_HAVE_SYSLOG #cmakedefine LWAN_HAVE_STPCPY #cmakedefine LWAN_HAVE_EVENTFD +#cmakedefine LWAN_HAVE_MINCORE /* Compiler builtins for specific CPU instruction support */ #cmakedefine LWAN_HAVE_BUILTIN_CLZLL diff --git a/src/lib/lwan-mod-serve-files.c b/src/lib/lwan-mod-serve-files.c index 2e88829d5..8a5bcc149 100644 --- a/src/lib/lwan-mod-serve-files.c +++ b/src/lib/lwan-mod-serve-files.c @@ -50,6 +50,10 @@ #include #endif +#define MMAP_SIZE_THRESHOLD 16384 +#define MINCORE_CALL_THRESHOLD 10 +#define MINCORE_VEC_LEN(len) (((len) + PAGE_SIZE - 1) / PAGE_SIZE) + static const struct lwan_key_value deflate_compression_hdr[] = { {"Content-Encoding", "deflate"}, {} }; @@ -113,6 +117,7 @@ struct mmap_cache_data { #if defined(LWAN_HAVE_ZSTD) struct lwan_value zstd; #endif + int mincore_call_threshold; }; struct sendfile_cache_data { @@ -544,6 +549,8 @@ static bool mmap_init(struct file_cache_entry *ce, ce->mime_type = lwan_determine_mime_type_for_file_name(full_path + priv->root_path_len); + md->mincore_call_threshold = MINCORE_CALL_THRESHOLD; + return true; } @@ -755,7 +762,7 @@ static const struct cache_funcs *get_funcs(struct serve_files_priv *priv, /* It's not a directory: choose the fastest way to serve the file * judging by its size. */ - if (st->st_size < 16384) + if (st->st_size < MMAP_SIZE_THRESHOLD) return &mmap_funcs; return &sendfile_funcs; @@ -1252,6 +1259,28 @@ static enum lwan_http_status mmap_serve(struct lwan_request *request, return serve_value_ok(request, fce->mime_type, to_serve, compression_hdr); +#ifdef LWAN_HAVE_MINCORE + if (md->mincore_call_threshold-- == 0) { + unsigned char mincore_vec[MINCORE_VEC_LEN(MMAP_SIZE_THRESHOLD)]; + + if (!mincore(to_serve->value, to_serve->len, mincore_vec)) { + const size_t pgs = MINCORE_VEC_LEN(to_serve->len); + + for (size_t pg = 0; pg < pgs; pg++) { + if (mincore_vec[pg] & 0x01) + continue; + + /* FIXME: madvise only the page that's not in core */ + lwan_madvise_queue(to_serve->value, to_serve->len); + coro_yield(request->conn->coro, CONN_CORO_WANT_WRITE); + break; + } + } + + md->mincore_call_threshold = MINCORE_CALL_THRESHOLD; + } +#endif + off_t from, to; enum lwan_http_status status = compute_range(request, &from, &to, (off_t)to_serve->len);