From 3ef0876b95a6ff342bc348f5603ae282265f0ca1 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 12 Nov 2014 10:43:32 +0100 Subject: [PATCH] THP detection / reporting functions added. --- src/latency.c | 26 ++++++++++++++++++++++++++ src/zmalloc.c | 24 ++++++++++++++++++------ src/zmalloc.h | 1 + 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/latency.c b/src/latency.c index b7845ca2..2e239571 100644 --- a/src/latency.c +++ b/src/latency.c @@ -56,6 +56,32 @@ dictType latencyTimeSeriesDictType = { dictVanillaFree /* val destructor */ }; +/* ------------------------- Utility functions ------------------------------ */ + +#ifdef __linux__ +/* Returns 1 if Transparent Huge Pages support is enabled in the kernel. + * Otherwise (or if we are unable to check) 0 is returned. */ +int THPIsEnabled(void) { + char buf[1024]; + + FILE *fp = fopen("/sys/kernel/mm/transparent_hugepage/enabled","r"); + if (!fp) return 0; + if (fgets(buf,sizeof(buf),fp) == NULL) { + fclose(fp); + return 0; + } + fclose(fp); + return (strstr(buf,"[never]") == NULL) ? 1 : 0; +} + +/* Report the amount of AnonHugePages in smap, in bytes. If the return + * value of the function is non-zero, the process is being targeted by + * THP support, and is likely to have memory usage / latency issues. */ +int THPGetAnonHugePagesSize(void) { + return zmalloc_get_smap_bytes_by_field("AnonHugePages:"); +} +#endif + /* ---------------------------- Latency API --------------------------------- */ /* Latency monitor initialization. We just need to create the dictionary diff --git a/src/zmalloc.c b/src/zmalloc.c index 11616e5a..e5835372 100644 --- a/src/zmalloc.c +++ b/src/zmalloc.c @@ -328,27 +328,39 @@ float zmalloc_get_fragmentation_ratio(size_t rss) { return (float)rss/zmalloc_used_memory(); } +/* Get the sum of the specified field (converted form kb to bytes) in + * /proc/self/smaps. The field must be specified with trailing ":" as it + * apperas in the smaps output. + * + * Example: zmalloc_get_smap_bytes_by_field("Rss:"); + */ #if defined(HAVE_PROC_SMAPS) -size_t zmalloc_get_private_dirty(void) { +size_t zmalloc_get_smap_bytes_by_field(char *field) { char line[1024]; - size_t pd = 0; + size_t bytes = 0; FILE *fp = fopen("/proc/self/smaps","r"); + int flen = strlen(field); if (!fp) return 0; while(fgets(line,sizeof(line),fp) != NULL) { - if (strncmp(line,"Private_Dirty:",14) == 0) { + if (strncmp(line,field,flen) == 0) { char *p = strchr(line,'k'); if (p) { *p = '\0'; - pd += strtol(line+14,NULL,10) * 1024; + bytes += strtol(line+flen,NULL,10) * 1024; } } } fclose(fp); - return pd; + return bytes; } #else -size_t zmalloc_get_private_dirty(void) { +size_t zmalloc_get_smap_bytes_by_field(char *field) { + REDIS_NOTUSED(field); return 0; } #endif + +size_t zmalloc_get_private_dirty(void) { + return zmalloc_get_smap_bytes_by_field("Private_Dirty:"); +} diff --git a/src/zmalloc.h b/src/zmalloc.h index 72a4f813..4de2cffe 100644 --- a/src/zmalloc.h +++ b/src/zmalloc.h @@ -76,6 +76,7 @@ void zmalloc_set_oom_handler(void (*oom_handler)(size_t)); float zmalloc_get_fragmentation_ratio(size_t rss); size_t zmalloc_get_rss(void); size_t zmalloc_get_private_dirty(void); +size_t zmalloc_get_smap_bytes_by_field(char *field); void zlibc_free(void *ptr); #ifndef HAVE_MALLOC_SIZE