- get_default_route_netif_index(): UDP connect trick + getifaddrs to find default route iface - etcp_socket_add(): auto-detect netif_index when not specified in config - queue_new() API: explicit index_offset/index_size params instead of implicit from hash_size - radix: cleanup types (uint8_t*), replace bzero/bcmp with memset/memcmp, remove kernel ifdefs - route6_lib: new IPv6 routing library + get_node_v6_routes()
157 lines
5.3 KiB
C
157 lines
5.3 KiB
C
/**
|
||
* Intensive memory pool test to demonstrate optimization benefits
|
||
* Updated for new ll_queue API
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <assert.h>
|
||
#include <time.h>
|
||
#include <unistd.h>
|
||
|
||
#include "../lib/ll_queue.h"
|
||
#include "../lib/memory_pool.h"
|
||
#include "../lib/u_async.h"
|
||
#include "../lib/debug_config.h"
|
||
|
||
static int waiter_callback_count = 0;
|
||
|
||
static void intensive_waiter_callback(struct ll_queue* q, void* arg) {
|
||
(void)q; (void)arg;
|
||
waiter_callback_count++;
|
||
}
|
||
|
||
// Тест без пулов памяти
|
||
static double test_without_pools(int iterations) {
|
||
clock_t start = clock();
|
||
|
||
struct UASYNC* ua = uasync_create();
|
||
struct ll_queue* queue = queue_new(ua, 0, 0, 0,"q1"); // Без пулов
|
||
|
||
for (int cycle = 0; cycle < iterations; cycle++) {
|
||
// Создать много waiters
|
||
struct queue_waiter* waiters[32];
|
||
for (int i = 0; i < 32; i++) {
|
||
waiters[i] = queue_wait_threshold(queue, i, 0, intensive_waiter_callback, NULL);
|
||
}
|
||
|
||
// Добавить записи
|
||
for (int i = 0; i < 10; i++) {
|
||
void* data = queue_entry_new(64);
|
||
queue_data_put(queue, data); // Используем ID = i
|
||
}
|
||
|
||
// Удалить записи (триггер waiters)
|
||
for (int i = 0; i < 10; i++) {
|
||
void* retrieved = queue_data_get(queue);
|
||
if (retrieved) {
|
||
queue_entry_free(retrieved);
|
||
}
|
||
}
|
||
|
||
// Отменить waiters
|
||
for (int i = 0; i < 32; i++) {
|
||
if (waiters[i]) {
|
||
queue_cancel_wait(queue, waiters[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
queue_free(queue);
|
||
uasync_destroy(ua, 0);
|
||
|
||
clock_t end = clock();
|
||
return ((double)(end - start)) / CLOCKS_PER_SEC;
|
||
}
|
||
|
||
// Тест с пулами памяти
|
||
static double test_with_pools(int iterations) {
|
||
clock_t start = clock();
|
||
|
||
struct UASYNC* ua = uasync_create();
|
||
struct ll_queue* queue = queue_new(ua, 0, 0, 0,"q2"); // С пулами
|
||
|
||
// Создать пул памяти для данных
|
||
struct memory_pool* pool = memory_pool_init(sizeof(struct ll_entry) + 64);
|
||
if (!pool) {
|
||
queue_free(queue);
|
||
uasync_destroy(ua, 0);
|
||
return -1.0;
|
||
}
|
||
|
||
for (int cycle = 0; cycle < iterations; cycle++) {
|
||
// Создать много waiters
|
||
struct queue_waiter* waiters[32];
|
||
for (int i = 0; i < 32; i++) {
|
||
waiters[i] = queue_wait_threshold(queue, i, 0, intensive_waiter_callback, NULL);
|
||
}
|
||
|
||
// Добавить записи из пула
|
||
for (int i = 0; i < 10; i++) {
|
||
void* data = queue_entry_new_from_pool(pool);
|
||
if (data) {
|
||
queue_data_put(queue, data); // Используем ID = i
|
||
}
|
||
}
|
||
|
||
// Удалить записи (триггер waiters)
|
||
for (int i = 0; i < 10; i++) {
|
||
void* retrieved = queue_data_get(queue);
|
||
if (retrieved) {
|
||
queue_entry_free(retrieved); // Вернется в пул
|
||
}
|
||
}
|
||
|
||
// Отменить waiters
|
||
for (int i = 0; i < 32; i++) {
|
||
if (waiters[i]) {
|
||
queue_cancel_wait(queue, waiters[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
queue_free(queue);
|
||
memory_pool_destroy(pool);
|
||
uasync_destroy(ua, 0);
|
||
|
||
clock_t end = clock();
|
||
return ((double)(end - start)) / CLOCKS_PER_SEC;
|
||
}
|
||
|
||
int main() {
|
||
debug_config_init();
|
||
debug_set_level(DEBUG_LEVEL_TRACE);
|
||
debug_set_categories(DEBUG_CATEGORY_ALL);
|
||
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "=== Интенсивный тест пулов памяти ===");
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Тестируется производительность с пулами vs без пулов");
|
||
|
||
const int iterations = 1000;
|
||
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Запуск теста без пулов памяти...");
|
||
double time_without = test_without_pools(iterations);
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Время без пулов: %.3f сек", time_without);
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Waiter callbacks: %d", waiter_callback_count);
|
||
|
||
waiter_callback_count = 0;
|
||
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Запуск теста с пулами памяти...");
|
||
double time_with = test_with_pools(iterations);
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Время с пулами: %.3f сек", time_with);
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Waiter callbacks: %d", waiter_callback_count);
|
||
|
||
if (time_with > 0 && time_without > 0) {
|
||
double speedup = time_without / time_with;
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "Результат: пулы памяти дали %.2fx ускорение", speedup);
|
||
if (time_with < time_without) {
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "✅ Пулы памяти эффективны!");
|
||
} else {
|
||
DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "⚠️ Пулы памяти не дали преимущества в этом тесте");
|
||
}
|
||
} else {
|
||
DEBUG_ERROR(DEBUG_CATEGORY_MEMORY, "❌ Ошибка в тесте с пулами");
|
||
}
|
||
|
||
return 0;
|
||
} |