From 341e288e98bb6931992d7dda68df0db17e28427f Mon Sep 17 00:00:00 2001 From: Boaz Date: Thu, 16 Jul 2015 16:11:16 +0300 Subject: [PATCH] With Tomer. Optimizing the performance counter queries on win32. There is now a cache for 1 second to all performance counter data. --- include/sigar_private.h | 2 + src/os/win32/sigar_os.h | 11 ++++- src/os/win32/win32_sigar.c | 98 ++++++++++++++++++++++---------------- 3 files changed, 68 insertions(+), 43 deletions(-) diff --git a/include/sigar_private.h b/include/sigar_private.h index 484f8306..11e62cd8 100644 --- a/include/sigar_private.h +++ b/include/sigar_private.h @@ -153,6 +153,8 @@ #define SIGAR_LAST_PROC_EXPIRE 2 +#define SIGAR_BUFFER_EXPIRE 1000 + #define SIGAR_FS_MAX 10 #define SIGAR_CPU_INFO_MAX 4 diff --git a/src/os/win32/sigar_os.h b/src/os/win32/sigar_os.h index e98de45d..f1b01e58 100755 --- a/src/os/win32/sigar_os.h +++ b/src/os/win32/sigar_os.h @@ -570,14 +570,21 @@ typedef struct { sigar_dll_func_t end; } sigar_mpr_t; +typedef struct +{ + char *buffer; + DWORD size; + time_t create_time; +} buffer_t; + struct sigar_t { SIGAR_T_BASE; char *machine; int using_wide; long pagesize; HKEY handle; - char *perfbuf; - DWORD perfbuf_size; + buffer_t* performanceBuffer; + buffer_t* processesBuffer; sigar_wtsapi_t wtsapi; sigar_iphlpapi_t iphlpapi; sigar_advapi_t advapi; diff --git a/src/os/win32/win32_sigar.c b/src/os/win32/win32_sigar.c index f53b5e9a..29126871 100755 --- a/src/os/win32/win32_sigar.c +++ b/src/os/win32/win32_sigar.c @@ -30,7 +30,7 @@ #define USING_WIDE_S(s) (s)->using_wide #define USING_WIDE() USING_WIDE_S(sigar) -#define PERFBUF_SIZE 8192 +#define BUFFER_SIZE 8192 #define PERF_TITLE_PROC 230 #define PERF_TITLE_SYS_KEY "2" @@ -111,11 +111,11 @@ typedef enum { (USING_WIDE() ? \ RegQueryValueExW(sigar->handle, \ wcounter_key, NULL, &type, \ - sigar->perfbuf, \ + sigar->performanceBuffer->buffer, \ &bytes) : \ RegQueryValueExA(sigar->handle, \ counter_key, NULL, &type, \ - sigar->perfbuf, \ + sigar->performanceBuffer->buffer, \ &bytes)) #define PERF_VAL(ix) \ @@ -145,24 +145,25 @@ sigar_uint64_t sigar_FileTimeToTime(FILETIME *ft) return time; } -static DWORD perfbuf_init(sigar_t *sigar) +static DWORD buffer_init(buffer_t *buffer) { - if (!sigar->perfbuf) { - sigar->perfbuf = malloc(PERFBUF_SIZE); - sigar->perfbuf_size = PERFBUF_SIZE; + if (!buffer->buffer) { + buffer->buffer = malloc(BUFFER_SIZE); + buffer->size = BUFFER_SIZE; + buffer->create_time = 0; } - return sigar->perfbuf_size; + return BUFFER_SIZE; } -static DWORD perfbuf_grow(sigar_t *sigar) +static DWORD buffer_grow(buffer_t *buffer) { - sigar->perfbuf_size += PERFBUF_SIZE; + buffer->size += BUFFER_SIZE; - sigar->perfbuf = - realloc(sigar->perfbuf, sigar->perfbuf_size); + buffer->buffer = + realloc(buffer->buffer, buffer->size); - return sigar->perfbuf_size; + return buffer->size; } static char *get_counter_name(char *key) @@ -199,11 +200,11 @@ static PERF_OBJECT_TYPE *get_perf_object_inst(sigar_t *sigar, SIGAR_A2W(counter_key, wcounter_key, sizeof(wcounter_key)); } - bytes = perfbuf_init(sigar); - + bytes = buffer_init(sigar->performanceBuffer); + while ((retval = MyRegQueryValue()) != ERROR_SUCCESS) { if (retval == ERROR_MORE_DATA) { - bytes = perfbuf_grow(sigar); + bytes = buffer_grow(sigar->performanceBuffer); } else { *err = retval; @@ -211,7 +212,7 @@ static PERF_OBJECT_TYPE *get_perf_object_inst(sigar_t *sigar, } } - block = (PERF_DATA_BLOCK *)sigar->perfbuf; + block = (PERF_DATA_BLOCK *)sigar->performanceBuffer->buffer; if (block->NumObjectTypes == 0) { counter_key = get_counter_name(counter_key); sigar_strerror_printf(sigar, "No %s counters defined (disabled?)", @@ -219,6 +220,8 @@ static PERF_OBJECT_TYPE *get_perf_object_inst(sigar_t *sigar, *err = -1; return NULL; } + + sigar->performanceBuffer->create_time = time(NULL); object = PdhFirstObject(block); /* @@ -542,8 +545,12 @@ int sigar_os_open(sigar_t **sigar_ptr) sigar->machine = ""; /* local machine */ sigar->using_wide = 0; /*XXX*/ - sigar->perfbuf = NULL; - sigar->perfbuf_size = 0; + sigar->performanceBuffer = (buffer_t*) malloc(sizeof(buffer_t)); + sigar->processesBuffer = (buffer_t*) malloc(sizeof(buffer_t)); + sigar->performanceBuffer->buffer = NULL; + sigar->processesBuffer->buffer = NULL; + buffer_init(sigar->performanceBuffer); + buffer_init(sigar->processesBuffer); version.dwOSVersionInfoSize = sizeof(version); GetVersionEx(&version); @@ -607,6 +614,14 @@ void dllmod_init_ntdll(sigar_t *sigar) DLLMOD_INIT(ntdll, FALSE); } +void buffer_free(buffer_t* buffer) +{ + if (buffer) { + free(buffer->buffer); + free(buffer); + } +} + int sigar_os_close(sigar_t *sigar) { int retval; @@ -620,9 +635,8 @@ int sigar_os_close(sigar_t *sigar) DLLMOD_FREE(kernel); DLLMOD_FREE(mpr); - if (sigar->perfbuf) { - free(sigar->perfbuf); - } + buffer_free(sigar->processesBuffer); + buffer_free(sigar->performanceBuffer); retval = RegCloseKey(sigar->handle); @@ -1145,25 +1159,23 @@ int sigar_os_proc_list_get(sigar_t *sigar, if (sigar_EnumProcesses) { DWORD retval, *pids; DWORD size = 0, i; + + do { + if (size == 0) { + size = buffer_init(sigar->processesBuffer); + } + else { + size = buffer_grow(sigar); + } - do { - /* re-use the perfbuf */ - if (size == 0) { - size = perfbuf_init(sigar); - } - else { - size = perfbuf_grow(sigar); - } - - if (!sigar_EnumProcesses((DWORD *)sigar->perfbuf, - sigar->perfbuf_size, - &retval)) - { - return GetLastError(); - } - } while (retval == sigar->perfbuf_size); //unlikely - - pids = (DWORD *)sigar->perfbuf; + if (!sigar_EnumProcesses((DWORD *)sigar->processesBuffer->buffer, + sigar->processesBuffer->size, + &retval)) { + return GetLastError(); + } + } while (retval == sigar->processesBuffer->size); //unlikely + + pids = (DWORD *)sigar->processesBuffer->buffer; size = retval / sizeof(DWORD); @@ -1408,7 +1420,11 @@ static int get_proc_info(sigar_t *sigar, sigar_pid_t pid) memset(&perf_offsets, 0, sizeof(perf_offsets)); - object = get_process_object(sigar, &err); + if ((timenow - sigar->performanceBuffer->create_time) < SIGAR_BUFFER_EXPIRE) { + object = PdhFirstObject(((PERF_DATA_BLOCK *)sigar->performanceBuffer->buffer)); + } else { + object = get_process_object(sigar, &err); + } if (object == NULL) { return err;