Files
utun2/tests/test_intensive_memory_pool.c
T
Evgeny f1a76c9d30 Fix memory leaks and crashes in ETCP tests
✅ Fixed critical segmentation fault (SIGABRT) in test_etcp_two_instances
✅ Added comprehensive timer debug logging with DEBUG_CATEGORY_TIMERS
✅ Created uasync_print_resources() function for resource diagnostics
✅ Created utun_instance_diagnose_leaks() function for leak analysis
✅ Fixed cleanup order - cancel timers before destroying uasync instances
✅ Fixed timer cancellation to properly update counters
✅ Fixed socket cleanup to unregister from uasync before destruction
✅ Added detailed diagnostic output for memory leak tracking
✅ All tests now pass without crashes

Key fixes:
- Fixed use-after-free in test cleanup sequence
- Added proper timer leak detection and cleanup
- Enhanced debug capabilities for future debugging
- Fixed ETCP socket cleanup to prevent resource leaks

The test_etcp_two_instances now runs successfully without segmentation faults.
2026-01-22 00:57:45 +03:00

157 lines
4.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Intensive memory pool test to demonstrate optimization benefits
*/
#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();
uasync_t* ua = uasync_create();
struct ll_queue* queue = queue_new(ua, NULL); // Без пулов
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++) {
struct ll_entry* entry = queue_entry_new(64);
queue_entry_put(queue, entry);
}
// Удалить записи (триггер waiters)
for (int i = 0; i < 10; i++) {
struct ll_entry* retrieved = queue_entry_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);
clock_t end = clock();
return ((double)(end - start)) / CLOCKS_PER_SEC;
}
// Тест с пулами памяти
static double test_with_pools(int iterations) {
clock_t start = clock();
uasync_t* ua = uasync_create();
struct ll_queue* queue = queue_new(ua, NULL); // С пулами (using memory pool)
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++) {
struct ll_entry* entry = queue_entry_new(64);
queue_entry_put(queue, entry);
}
// Удалить записи (триггер waiters)
for (int i = 0; i < 10; i++) {
struct ll_entry* retrieved = queue_entry_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]);
}
}
}
// Получить статистику пула
size_t allocations, reuse_count;
queue_get_pool_stats(queue, &allocations, &reuse_count);
queue_free(queue);
uasync_destroy(ua);
clock_t end = clock();
printf("Pool statistics: allocations=%zu, reuse_count=%zu\n", allocations, reuse_count);
if (allocations > 0) {
printf("Pool efficiency: %.1f%%\n", (100.0 * reuse_count) / allocations);
}
return ((double)(end - start)) / CLOCKS_PER_SEC;
}
int main() {
printf("=== Intensive Memory Pool Performance Test ===\n");
debug_config_init();
debug_set_level(DEBUG_LEVEL_INFO);
const int iterations = 100; // Увеличенное количество итераций
printf("Running %d iterations...\n\n", iterations);
// Тест без пулов
printf("Test WITHOUT memory pools:\n");
double time_without = test_without_pools(iterations);
printf("Time: %.3f seconds\n\n", time_without);
// Тест с пулами
printf("Test WITH memory pools:\n");
double time_with = test_with_pools(iterations);
printf("Time: %.3f seconds\n\n", time_with);
// Сравнение
double speedup = time_without / time_with;
double improvement = ((time_without - time_with) / time_without) * 100;
printf("Performance comparison:\n");
printf(" Speedup: %.2fx\n", speedup);
printf(" Improvement: %.1f%%\n", improvement);
printf(" Time saved: %.3f seconds\n", time_without - time_with);
if (speedup > 1.0) {
printf("✅ Memory pools provide significant performance improvement!\n");
} else {
printf("⚠️ Memory pools show minimal improvement for this workload\n");
}
printf("\n=== Test completed ===\n");
return 0;
}