With Tomer.

Optimizing the performance counter queries on win32.

There is now a cache for 1 second to all performance counter data.
This commit is contained in:
Boaz 2015-07-16 16:11:16 +03:00
parent 0928a780f4
commit 341e288e98
3 changed files with 68 additions and 43 deletions

View File

@ -153,6 +153,8 @@
#define SIGAR_LAST_PROC_EXPIRE 2 #define SIGAR_LAST_PROC_EXPIRE 2
#define SIGAR_BUFFER_EXPIRE 1000
#define SIGAR_FS_MAX 10 #define SIGAR_FS_MAX 10
#define SIGAR_CPU_INFO_MAX 4 #define SIGAR_CPU_INFO_MAX 4

View File

@ -570,14 +570,21 @@ typedef struct {
sigar_dll_func_t end; sigar_dll_func_t end;
} sigar_mpr_t; } sigar_mpr_t;
typedef struct
{
char *buffer;
DWORD size;
time_t create_time;
} buffer_t;
struct sigar_t { struct sigar_t {
SIGAR_T_BASE; SIGAR_T_BASE;
char *machine; char *machine;
int using_wide; int using_wide;
long pagesize; long pagesize;
HKEY handle; HKEY handle;
char *perfbuf; buffer_t* performanceBuffer;
DWORD perfbuf_size; buffer_t* processesBuffer;
sigar_wtsapi_t wtsapi; sigar_wtsapi_t wtsapi;
sigar_iphlpapi_t iphlpapi; sigar_iphlpapi_t iphlpapi;
sigar_advapi_t advapi; sigar_advapi_t advapi;

View File

@ -30,7 +30,7 @@
#define USING_WIDE_S(s) (s)->using_wide #define USING_WIDE_S(s) (s)->using_wide
#define USING_WIDE() USING_WIDE_S(sigar) #define USING_WIDE() USING_WIDE_S(sigar)
#define PERFBUF_SIZE 8192 #define BUFFER_SIZE 8192
#define PERF_TITLE_PROC 230 #define PERF_TITLE_PROC 230
#define PERF_TITLE_SYS_KEY "2" #define PERF_TITLE_SYS_KEY "2"
@ -111,11 +111,11 @@ typedef enum {
(USING_WIDE() ? \ (USING_WIDE() ? \
RegQueryValueExW(sigar->handle, \ RegQueryValueExW(sigar->handle, \
wcounter_key, NULL, &type, \ wcounter_key, NULL, &type, \
sigar->perfbuf, \ sigar->performanceBuffer->buffer, \
&bytes) : \ &bytes) : \
RegQueryValueExA(sigar->handle, \ RegQueryValueExA(sigar->handle, \
counter_key, NULL, &type, \ counter_key, NULL, &type, \
sigar->perfbuf, \ sigar->performanceBuffer->buffer, \
&bytes)) &bytes))
#define PERF_VAL(ix) \ #define PERF_VAL(ix) \
@ -145,24 +145,25 @@ sigar_uint64_t sigar_FileTimeToTime(FILETIME *ft)
return time; return time;
} }
static DWORD perfbuf_init(sigar_t *sigar) static DWORD buffer_init(buffer_t *buffer)
{ {
if (!sigar->perfbuf) { if (!buffer->buffer) {
sigar->perfbuf = malloc(PERFBUF_SIZE); buffer->buffer = malloc(BUFFER_SIZE);
sigar->perfbuf_size = PERFBUF_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 = buffer->buffer =
realloc(sigar->perfbuf, sigar->perfbuf_size); realloc(buffer->buffer, buffer->size);
return sigar->perfbuf_size; return buffer->size;
} }
static char *get_counter_name(char *key) 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)); SIGAR_A2W(counter_key, wcounter_key, sizeof(wcounter_key));
} }
bytes = perfbuf_init(sigar); bytes = buffer_init(sigar->performanceBuffer);
while ((retval = MyRegQueryValue()) != ERROR_SUCCESS) { while ((retval = MyRegQueryValue()) != ERROR_SUCCESS) {
if (retval == ERROR_MORE_DATA) { if (retval == ERROR_MORE_DATA) {
bytes = perfbuf_grow(sigar); bytes = buffer_grow(sigar->performanceBuffer);
} }
else { else {
*err = retval; *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) { if (block->NumObjectTypes == 0) {
counter_key = get_counter_name(counter_key); counter_key = get_counter_name(counter_key);
sigar_strerror_printf(sigar, "No %s counters defined (disabled?)", 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; *err = -1;
return NULL; return NULL;
} }
sigar->performanceBuffer->create_time = time(NULL);
object = PdhFirstObject(block); object = PdhFirstObject(block);
/* /*
@ -542,8 +545,12 @@ int sigar_os_open(sigar_t **sigar_ptr)
sigar->machine = ""; /* local machine */ sigar->machine = ""; /* local machine */
sigar->using_wide = 0; /*XXX*/ sigar->using_wide = 0; /*XXX*/
sigar->perfbuf = NULL; sigar->performanceBuffer = (buffer_t*) malloc(sizeof(buffer_t));
sigar->perfbuf_size = 0; 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); version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx(&version); GetVersionEx(&version);
@ -607,6 +614,14 @@ void dllmod_init_ntdll(sigar_t *sigar)
DLLMOD_INIT(ntdll, FALSE); 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 sigar_os_close(sigar_t *sigar)
{ {
int retval; int retval;
@ -620,9 +635,8 @@ int sigar_os_close(sigar_t *sigar)
DLLMOD_FREE(kernel); DLLMOD_FREE(kernel);
DLLMOD_FREE(mpr); DLLMOD_FREE(mpr);
if (sigar->perfbuf) { buffer_free(sigar->processesBuffer);
free(sigar->perfbuf); buffer_free(sigar->performanceBuffer);
}
retval = RegCloseKey(sigar->handle); retval = RegCloseKey(sigar->handle);
@ -1146,24 +1160,22 @@ int sigar_os_proc_list_get(sigar_t *sigar,
DWORD retval, *pids; DWORD retval, *pids;
DWORD size = 0, i; DWORD size = 0, i;
do { do {
/* re-use the perfbuf */ if (size == 0) {
if (size == 0) { size = buffer_init(sigar->processesBuffer);
size = perfbuf_init(sigar); }
} else {
else { size = buffer_grow(sigar);
size = perfbuf_grow(sigar); }
}
if (!sigar_EnumProcesses((DWORD *)sigar->perfbuf, if (!sigar_EnumProcesses((DWORD *)sigar->processesBuffer->buffer,
sigar->perfbuf_size, sigar->processesBuffer->size,
&retval)) &retval)) {
{ return GetLastError();
return GetLastError(); }
} } while (retval == sigar->processesBuffer->size); //unlikely
} while (retval == sigar->perfbuf_size); //unlikely
pids = (DWORD *)sigar->perfbuf; pids = (DWORD *)sigar->processesBuffer->buffer;
size = retval / sizeof(DWORD); 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)); 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) { if (object == NULL) {
return err; return err;