Align statistics to cache lines
Aligning the statistics object indices to cache line size reduces the CPU overhead of gathering the statistics. This allows the statistics to more accurately measure the polling system without the measurement affecting the outcome.
This commit is contained in:
@ -40,13 +40,18 @@ enum ts_stats_type
|
|||||||
TS_STATS_AVG /**< Average of all values */
|
TS_STATS_AVG /**< Average of all values */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** stats_init should be called only once */
|
/**
|
||||||
void ts_stats_init();
|
* @brief Allocate a new statistics object
|
||||||
|
*
|
||||||
/** No-op for now */
|
* @return New statistics object or NULL if memory allocation failed
|
||||||
void ts_stats_end();
|
*/
|
||||||
|
|
||||||
ts_stats_t ts_stats_alloc();
|
ts_stats_t ts_stats_alloc();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free statistics
|
||||||
|
*
|
||||||
|
* @param stats Statistics to free
|
||||||
|
*/
|
||||||
void ts_stats_free(ts_stats_t stats);
|
void ts_stats_free(ts_stats_t stats);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,11 +71,7 @@ int64_t ts_stats_get(ts_stats_t stats, enum ts_stats_type type);
|
|||||||
* @param stats Statistics to add to
|
* @param stats Statistics to add to
|
||||||
* @param thread_id ID of thread
|
* @param thread_id ID of thread
|
||||||
*/
|
*/
|
||||||
static void inline
|
void ts_stats_increment(ts_stats_t stats, int thread_id);
|
||||||
ts_stats_increment(ts_stats_t stats, int thread_id)
|
|
||||||
{
|
|
||||||
((int64_t*)stats)[thread_id]++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Assign a value to a statistics element
|
* @brief Assign a value to a statistics element
|
||||||
@ -81,11 +82,7 @@ ts_stats_increment(ts_stats_t stats, int thread_id)
|
|||||||
* @param value Value to set to
|
* @param value Value to set to
|
||||||
* @param thread_id ID of thread
|
* @param thread_id ID of thread
|
||||||
*/
|
*/
|
||||||
static void inline
|
void ts_stats_set(ts_stats_t stats, int value, int thread_id);
|
||||||
ts_stats_set(ts_stats_t stats, int value, int thread_id)
|
|
||||||
{
|
|
||||||
((int64_t*)stats)[thread_id] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Assign the maximum value to a statistics element
|
* @brief Assign the maximum value to a statistics element
|
||||||
@ -96,16 +93,7 @@ ts_stats_set(ts_stats_t stats, int value, int thread_id)
|
|||||||
* @param value Value to set to
|
* @param value Value to set to
|
||||||
* @param thread_id ID of thread
|
* @param thread_id ID of thread
|
||||||
*/
|
*/
|
||||||
static void inline
|
void ts_stats_set_max(ts_stats_t stats, int value, int thread_id);
|
||||||
ts_stats_set_max(ts_stats_t stats, int value, int thread_id)
|
|
||||||
{
|
|
||||||
int64_t *p = (int64_t*) stats;
|
|
||||||
|
|
||||||
if (value > p[thread_id])
|
|
||||||
{
|
|
||||||
p[thread_id] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Assign the minimum value to a statistics element
|
* @brief Assign the minimum value to a statistics element
|
||||||
@ -116,15 +104,6 @@ ts_stats_set_max(ts_stats_t stats, int value, int thread_id)
|
|||||||
* @param value Value to set to
|
* @param value Value to set to
|
||||||
* @param thread_id ID of thread
|
* @param thread_id ID of thread
|
||||||
*/
|
*/
|
||||||
static void inline
|
void ts_stats_set_min(ts_stats_t stats, int value, int thread_id);
|
||||||
ts_stats_set_min(ts_stats_t stats, int value, int thread_id)
|
|
||||||
{
|
|
||||||
int64_t *p = (int64_t*) stats;
|
|
||||||
|
|
||||||
if (value < p[thread_id])
|
|
||||||
{
|
|
||||||
p[thread_id] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MXS_END_DECLS
|
MXS_END_DECLS
|
||||||
|
@ -37,6 +37,12 @@ MXS_BEGIN_DECLS
|
|||||||
|
|
||||||
#define MXS_ARRAY_NELEMS(array) ((size_t)(sizeof(array)/sizeof(array[0])))
|
#define MXS_ARRAY_NELEMS(array) ((size_t)(sizeof(array)/sizeof(array[0])))
|
||||||
|
|
||||||
|
/** Macro for safe pointer arithmetic on void pointers
|
||||||
|
* @param a The void pointer
|
||||||
|
* @param b The offset into @c a
|
||||||
|
*/
|
||||||
|
#define MXS_PTR(a, b) (((uint8_t*)(a)) + (b))
|
||||||
|
|
||||||
bool utils_init(); /*< Call this first before using any other function */
|
bool utils_init(); /*< Call this first before using any other function */
|
||||||
void utils_end();
|
void utils_end();
|
||||||
|
|
||||||
|
@ -67,12 +67,12 @@
|
|||||||
#include <maxscale/query_classifier.h>
|
#include <maxscale/query_classifier.h>
|
||||||
#include <maxscale/server.h>
|
#include <maxscale/server.h>
|
||||||
#include <maxscale/session.h>
|
#include <maxscale/session.h>
|
||||||
#include <maxscale/statistics.h>
|
|
||||||
#include <maxscale/thread.h>
|
#include <maxscale/thread.h>
|
||||||
#include <maxscale/utils.h>
|
#include <maxscale/utils.h>
|
||||||
#include <maxscale/version.h>
|
#include <maxscale/version.h>
|
||||||
|
|
||||||
#include "maxscale/service.h"
|
#include "maxscale/service.h"
|
||||||
|
#include "maxscale/statistics.h"
|
||||||
|
|
||||||
#define STRING_BUFFER_SIZE 1024
|
#define STRING_BUFFER_SIZE 1024
|
||||||
#define PIDFD_CLOSED -1
|
#define PIDFD_CLOSED -1
|
||||||
|
37
server/core/maxscale/statistics.h
Normal file
37
server/core/maxscale/statistics.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||||
|
*
|
||||||
|
* Use of this software is governed by the Business Source License included
|
||||||
|
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||||
|
*
|
||||||
|
* Change Date: 2019-07-01
|
||||||
|
*
|
||||||
|
* On the date above, in accordance with the Business Source License, use
|
||||||
|
* of this software will be governed by version 2 or later of the General
|
||||||
|
* Public License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Internal code for the statistics system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <maxscale/statistics.h>
|
||||||
|
|
||||||
|
MXS_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize statistics system
|
||||||
|
*
|
||||||
|
* This function should only be called once by the MaxScale core.
|
||||||
|
*/
|
||||||
|
void ts_stats_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Terminate statistics system
|
||||||
|
*/
|
||||||
|
void ts_stats_end();
|
||||||
|
|
||||||
|
MXS_END_DECLS
|
@ -29,10 +29,32 @@
|
|||||||
#include <maxscale/config.h>
|
#include <maxscale/config.h>
|
||||||
#include <maxscale/debug.h>
|
#include <maxscale/debug.h>
|
||||||
#include <maxscale/platform.h>
|
#include <maxscale/platform.h>
|
||||||
|
#include <maxscale/utils.h>
|
||||||
|
|
||||||
static int thread_count = 0;
|
static int thread_count = 0;
|
||||||
|
static size_t cache_linesize = 0;
|
||||||
|
static size_t stats_size = 0;
|
||||||
static bool stats_initialized = false;
|
static bool stats_initialized = false;
|
||||||
|
|
||||||
|
static size_t get_cache_line_size()
|
||||||
|
{
|
||||||
|
size_t rval = 64; // Cache lines are 64 bytes for x86
|
||||||
|
|
||||||
|
#ifdef _SC_LEVEL1_DCACHE_LINESIZE
|
||||||
|
rval = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rval < sizeof(int64_t))
|
||||||
|
{
|
||||||
|
MXS_WARNING("Cache line size reported to be %lu bytes when a 64-bit "
|
||||||
|
"integer is %lu bytes. Increasing statistics to the minimum "
|
||||||
|
"size of %lu bytes.", rval, sizeof(int64_t), sizeof(int64_t));
|
||||||
|
rval = sizeof(int64_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the statistics gathering
|
* @brief Initialize the statistics gathering
|
||||||
*/
|
*/
|
||||||
@ -40,6 +62,8 @@ void ts_stats_init()
|
|||||||
{
|
{
|
||||||
ss_dassert(!stats_initialized);
|
ss_dassert(!stats_initialized);
|
||||||
thread_count = config_threadcount();
|
thread_count = config_threadcount();
|
||||||
|
cache_linesize = get_cache_line_size();
|
||||||
|
stats_size = thread_count * cache_linesize;
|
||||||
stats_initialized = true;
|
stats_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +83,7 @@ void ts_stats_end()
|
|||||||
ts_stats_t ts_stats_alloc()
|
ts_stats_t ts_stats_alloc()
|
||||||
{
|
{
|
||||||
ss_dassert(stats_initialized);
|
ss_dassert(stats_initialized);
|
||||||
return MXS_CALLOC(thread_count, sizeof(int64_t));
|
return MXS_CALLOC(thread_count, cache_linesize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,10 +109,12 @@ int64_t ts_stats_sum(ts_stats_t stats)
|
|||||||
{
|
{
|
||||||
ss_dassert(stats_initialized);
|
ss_dassert(stats_initialized);
|
||||||
int64_t sum = 0;
|
int64_t sum = 0;
|
||||||
for (int i = 0; i < thread_count; i++)
|
|
||||||
|
for (size_t i = 0; i < stats_size; i += cache_linesize)
|
||||||
{
|
{
|
||||||
sum += ((int64_t*)stats)[i];
|
sum += *((int64_t*)MXS_PTR(stats, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,9 +132,9 @@ int64_t ts_stats_get(ts_stats_t stats, enum ts_stats_type type)
|
|||||||
ss_dassert(stats_initialized);
|
ss_dassert(stats_initialized);
|
||||||
int64_t best = type == TS_STATS_MAX ? LONG_MIN : (type == TS_STATS_MIX ? LONG_MAX : 0);
|
int64_t best = type == TS_STATS_MAX ? LONG_MIN : (type == TS_STATS_MIX ? LONG_MAX : 0);
|
||||||
|
|
||||||
for (int i = 0; i < thread_count; i++)
|
for (size_t i = 0; i < stats_size; i += cache_linesize)
|
||||||
{
|
{
|
||||||
int64_t value = ((int64_t*)stats)[i];
|
int64_t value = *((int64_t*)MXS_PTR(stats, i));
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@ -135,3 +161,39 @@ int64_t ts_stats_get(ts_stats_t stats, enum ts_stats_type type)
|
|||||||
|
|
||||||
return type == TS_STATS_AVG ? best / thread_count : best;
|
return type == TS_STATS_AVG ? best / thread_count : best;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ts_stats_increment(ts_stats_t stats, int thread_id)
|
||||||
|
{
|
||||||
|
ss_dassert(thread_id < thread_count);
|
||||||
|
int64_t *item = (int64_t*)MXS_PTR(stats, thread_id * cache_linesize);
|
||||||
|
*item += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ts_stats_set(ts_stats_t stats, int value, int thread_id)
|
||||||
|
{
|
||||||
|
ss_dassert(thread_id < thread_count);
|
||||||
|
int64_t *item = (int64_t*)MXS_PTR(stats, thread_id * cache_linesize);
|
||||||
|
*item = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ts_stats_set_max(ts_stats_t stats, int value, int thread_id)
|
||||||
|
{
|
||||||
|
ss_dassert(thread_id < thread_count);
|
||||||
|
int64_t *item = (int64_t*)MXS_PTR(stats, thread_id * cache_linesize);
|
||||||
|
|
||||||
|
if (value > *item)
|
||||||
|
{
|
||||||
|
*item = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ts_stats_set_min(ts_stats_t stats, int value, int thread_id)
|
||||||
|
{
|
||||||
|
ss_dassert(thread_id < thread_count);
|
||||||
|
int64_t *item = (int64_t*)MXS_PTR(stats, thread_id * cache_linesize);
|
||||||
|
|
||||||
|
if (value < *item)
|
||||||
|
{
|
||||||
|
*item = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include <maxscale/housekeeper.h>
|
#include <maxscale/housekeeper.h>
|
||||||
#include <maxscale/maxscale_test.h>
|
#include <maxscale/maxscale_test.h>
|
||||||
#include <maxscale/log_manager.h>
|
#include <maxscale/log_manager.h>
|
||||||
#include <maxscale/statistics.h>
|
#include "../maxscale/statistics.h"
|
||||||
|
|
||||||
void init_test_env(char *path)
|
void init_test_env(char *path)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user