diff --git a/include/common.h b/include/common.h
index 853596394d..c606d8e845 100644
--- a/include/common.h
+++ b/include/common.h
@@ -440,6 +440,7 @@ zbx_graph_yaxis_types_t;
 #define ZBX_LOG_LEVEL_DECREASE	"log_level_decrease"
 #define ZBX_SNMP_CACHE_RELOAD	"snmp_cache_reload"
 #define ZBX_DIAGINFO		"diaginfo"
+#define ZBX_BENCH		"bench"
 
 /* value for not supported items */
 #define ZBX_NOTSUPPORTED	"ZBX_NOTSUPPORTED"
@@ -932,6 +933,7 @@ zbx_task_t;
 #define ZBX_RTC_CONFIG_CACHE_RELOAD	8
 #define ZBX_RTC_SNMP_CACHE_RELOAD	9
 #define ZBX_RTC_DIAGINFO		10
+#define ZBX_RTC_BENCH			11
 
 typedef enum
 {
diff --git a/src/libs/zbxcommon/misc.c b/src/libs/zbxcommon/misc.c
index 0165b413eb..1d0751329c 100644
--- a/src/libs/zbxcommon/misc.c
+++ b/src/libs/zbxcommon/misc.c
@@ -3856,3 +3856,20 @@ int	zbx_get_agent_item_nextcheck(zbx_uint64_t itemid, const char *delay, unsigne
 	return SUCCEED;
 }
 
+// WDN debug
+
+static time_t	vc_time;
+
+void	vc_set_time(time_t new_time)
+{
+	vc_time = new_time;
+}
+
+time_t	__wrap_time(time_t *ptr)
+{
+	if (NULL != ptr)
+		*ptr = vc_time;
+
+	return vc_time;
+}
+
diff --git a/src/libs/zbxnix/control.c b/src/libs/zbxnix/control.c
index 0d04cde9d4..e00581a5d6 100644
--- a/src/libs/zbxnix/control.c
+++ b/src/libs/zbxnix/control.c
@@ -213,6 +213,17 @@ int	parse_rtc_options(const char *opt, unsigned char program_type, int *message)
 			return FAIL;
 		}
 	}
+	else if (0 != (program_type & (ZBX_PROGRAM_TYPE_SERVER)) &&
+			0 == strncmp(opt, ZBX_BENCH, ZBX_CONST_STRLEN(ZBX_BENCH)))
+	{
+		command = ZBX_RTC_BENCH;
+		scope = 0;
+
+		if ('=' == opt[ZBX_CONST_STRLEN(ZBX_BENCH)])
+			data = atoi(opt + ZBX_CONST_STRLEN(ZBX_BENCH) + 1);
+		else
+			data = 0;
+	}
 	else
 	{
 		zbx_error("invalid runtime control option: %s", opt);
diff --git a/src/libs/zbxnix/daemon.c b/src/libs/zbxnix/daemon.c
index 5d16b0918a..54b32abab3 100644
--- a/src/libs/zbxnix/daemon.c
+++ b/src/libs/zbxnix/daemon.c
@@ -241,6 +241,9 @@ static void	user1_signal_handler(int sig, siginfo_t *siginfo, void *context)
 			zbx_signal_process_by_type(ZBX_PROCESS_TYPE_DISCOVERER, ZBX_RTC_GET_DATA(flags), flags);
 			zbx_signal_process_by_type(ZBX_PROCESS_TYPE_TASKMANAGER, ZBX_RTC_GET_DATA(flags), flags);
 			break;
+		case ZBX_RTC_BENCH:
+			zbx_signal_process_by_type(ZBX_PROCESS_TYPE_TRAPPER, 0, flags);
+			break;
 		default:
 			if (NULL != zbx_sigusr_handler)
 				zbx_sigusr_handler(flags);
diff --git a/src/zabbix_server/server.c b/src/zabbix_server/server.c
index 1f93832853..9f6e91944a 100644
--- a/src/zabbix_server/server.c
+++ b/src/zabbix_server/server.c
@@ -1136,6 +1136,9 @@ int	MAIN_ZABBIX_ENTRY(int flags)
 		exit(EXIT_FAILURE);
 	}
 
+	//  test
+	vc_prepare_cache();
+
 	if (ZBX_DB_UNKNOWN == (db_type = zbx_db_get_database_type()))
 	{
 		zabbix_log(LOG_LEVEL_CRIT, "cannot use database \"%s\": database is not a Zabbix database",
diff --git a/src/zabbix_server/trapper/trapper.c b/src/zabbix_server/trapper/trapper.c
index b23e424bc9..9b1f2a3136 100644
--- a/src/zabbix_server/trapper/trapper.c
+++ b/src/zabbix_server/trapper/trapper.c
@@ -1308,6 +1308,13 @@ static void	process_trapper_child(zbx_socket_t *sock, zbx_timespec_t *ts)
 	process_trap(sock, sock->buffer, ts);
 }
 
+// WDN: benchmarking
+static	sig_atomic_t vc_bench_range = 0;
+static	int vc_bench_range_last = 0;
+
+static void	vc_bench_cache(section);
+void	vc_set_time(time_t new_time);
+
 static void	zbx_trapper_sigusr_handler(int flags)
 {
 #ifdef HAVE_NETSNMP
@@ -1316,6 +1323,9 @@ static void	zbx_trapper_sigusr_handler(int flags)
 #else
 	ZBX_UNUSED(flags);
 #endif
+	// WDN: benchmarking
+	if (ZBX_RTC_BENCH == ZBX_RTC_GET_MSG(flags))
+		vc_bench_range = ZBX_RTC_GET_DATA(flags);
 }
 
 ZBX_THREAD_ENTRY(trapper_thread, args)
@@ -1355,6 +1365,10 @@ ZBX_THREAD_ENTRY(trapper_thread, args)
 
 	zbx_set_sigusr_handler(zbx_trapper_sigusr_handler);
 
+	// WDN: benchmarking
+	vc_bench_cache(process_num - 1);
+#ifdef WND_VOID
+
 	while (ZBX_IS_RUNNING())
 	{
 #ifdef HAVE_NETSNMP
@@ -1400,8 +1414,198 @@ ZBX_THREAD_ENTRY(trapper_thread, args)
 		}
 	}
 
+// WDN: benchmarking
+#endif
 	zbx_setproctitle("%s #%d [terminated]", get_process_type_string(process_type), process_num);
 
 	while (1)
 		zbx_sleep(SEC_PER_MIN);
 }
+
+// WDN: benchmarking
+
+static void	dc_history_clear(ZBX_DC_HISTORY *h)
+{
+	switch (h->value_type)
+	{
+		case ITEM_VALUE_TYPE_STR:
+		case ITEM_VALUE_TYPE_TEXT:
+			zbx_free(h->value.str);
+			break;
+		case ITEM_VALUE_TYPE_LOG:
+			zbx_free(h->value.log->source);
+			zbx_free(h->value.log->value);
+			zbx_free(h->value.log);
+			break;
+	}
+}
+
+static void	dc_history_free(void *ptr)
+{
+	dc_history_clear((ZBX_DC_HISTORY *)ptr);
+	zbx_free(ptr);
+}
+
+#define ZBX_VC_VALUE_TYPE	ITEM_VALUE_TYPE_FLOAT
+#define ZBX_VC_START_TIME	1612569600
+
+#define ZBX_VC_FIRST_ITEMID	1000001
+#define ZBX_VC_LAST_ITEMID	1010000
+//#define ZBX_VC_LAST_ITEMID	2000000
+
+#define  ZBX_VC_READ_RATIO	2
+
+#define ZBX_VC_PRECACHE_NUM	1000
+
+#include "../../libs/zbxdbcache/valuecache.h"
+#include "zbxdiag.h"
+
+static void	vc_cache_item(zbx_uint64_t itemid, unsigned char value_type)
+{
+	zbx_timespec_t			ts = {.sec = time(NULL)};
+	zbx_vector_history_record_t	values;
+
+	zbx_vector_history_record_create(&values);
+	zbx_vc_get_values(itemid, value_type, &values, (ZBX_VC_PRECACHE_NUM + 1) * SEC_PER_MIN, 0, &ts);
+	zbx_vc_flush_stats();
+	zbx_history_record_vector_destroy(&values, value_type);
+}
+
+void	vc_prepare_cache()
+{
+	int	i;
+
+	vc_set_time(ZBX_VC_START_TIME);
+	zbx_vc_enable();
+
+	for (i = ZBX_VC_FIRST_ITEMID; i <= ZBX_VC_LAST_ITEMID; i++)
+		vc_cache_item(i, ZBX_VC_VALUE_TYPE);
+
+	zabbix_log(LOG_LEVEL_INFORMATION, "value cache preparation complete");
+	zbx_diag_log_info(1 << ZBX_DIAGINFO_VALUECACHE);
+}
+
+static void	vc_bench_cache(int section)
+{
+	int			i, j, iters_num = 0;
+	zbx_timespec_t		ts_start, ts_end;
+	zbx_vector_ptr_t	history;
+
+	zbx_vector_ptr_create(&history);
+
+	while (ZBX_IS_RUNNING())
+	{
+		if (vc_bench_range_last != vc_bench_range)
+		{
+			if (0 != vc_bench_range_last)
+			{
+				int	diff;
+
+				zbx_timespec(&ts_end);
+
+				diff = (ts_end.sec - ts_start.sec) * 1e3 + (ts_end.ns - ts_start.ns) / 1e6;
+
+				zabbix_log(LOG_LEVEL_INFORMATION, "done, %.1f iterations/sec",
+						(double)iters_num * 1e3 / diff);
+
+				//zbx_diag_log_info(1 << ZBX_DIAGINFO_VALUECACHE);
+			}
+
+			if (0 != vc_bench_range)
+			{
+				zabbix_log(LOG_LEVEL_INFORMATION, "=== range:%d ratio:%d ===", vc_bench_range,
+						ZBX_VC_READ_RATIO);
+
+				zbx_timespec(&ts_start);
+				iters_num = 0;
+			}
+
+			vc_bench_range_last = vc_bench_range;
+		}
+
+		if (0 == vc_bench_range)
+		{
+			sleep(1);
+		}
+		else
+		{
+			time_t	now;
+
+			now = time(NULL);
+
+			/* add batch of values */
+
+			for (i = 0; i < 1000; i++)
+			{
+				ZBX_DC_HISTORY	*h;
+
+				h = (ZBX_DC_HISTORY *)zbx_malloc(NULL, sizeof(ZBX_DC_HISTORY));
+				memset(h, 0, sizeof(ZBX_DC_HISTORY));
+				h->itemid = ZBX_VC_FIRST_ITEMID + section * 1000 + i;
+				h->ts.sec = now;
+				h->ts.ns = i;
+				h->value.dbl = i;
+				zbx_vector_ptr_append(&history, h);
+			}
+
+			zbx_vc_add_values(&history);
+			zbx_vector_ptr_clear_ext(&history, dc_history_free);
+
+			for (j = 0; j < ZBX_VC_READ_RATIO; j++)
+			{
+				zbx_timespec_t			ts = {.sec = now};
+				zbx_vector_history_record_t	values;
+
+				for (i = 0; i < 1000; i++)
+				{
+					zbx_vector_history_record_create(&values);
+					zbx_vc_get_values(ZBX_VC_FIRST_ITEMID + section * 1000 + i, ZBX_VC_VALUE_TYPE,
+							&values, vc_bench_range * SEC_PER_MIN, 0, &ts);
+					zbx_history_record_vector_destroy(&values, ZBX_VC_VALUE_TYPE);
+				}
+			}
+
+			zbx_vc_flush_stats();
+
+			vc_set_time(now + SEC_PER_MIN);
+			iters_num++;
+		}
+	}
+
+	zbx_vector_ptr_destroy(&history);
+}
+
+int	__wrap_zbx_history_add_values(const zbx_vector_ptr_t *history)
+{
+	ZBX_UNUSED(history);
+	return SUCCEED;
+}
+
+int	__wrap_zbx_history_get_values(zbx_uint64_t itemid, int value_type, int start, int count, int end,
+		zbx_vector_history_record_t *values)
+{
+	int	i;
+
+	ZBX_UNUSED(itemid);
+	ZBX_UNUSED(value_type);
+	ZBX_UNUSED(start);
+	ZBX_UNUSED(count);
+
+	/* initial time based cache request will attempt to cache from the start period to future */
+	if (ZBX_JAN_2038 != end)
+		return SUCCEED;
+
+	for (i = 0; i < ZBX_VC_PRECACHE_NUM; i++)
+	{
+		zbx_history_record_t	h;
+
+		h.timestamp.sec = ZBX_VC_START_TIME - (i + 1) * SEC_PER_MIN;
+		h.timestamp.ns = 0;
+		h.value.dbl = i;
+
+		zbx_vector_history_record_append_ptr(values, &h);
+	}
+
+	return SUCCEED;
+}
+
