MT#55283 use fixed allocation size

Allocate all bufferpool shards of the same size, regardless of
underlying allocator. This way increase memory usage a bit, but we're
already quite heavy on that, so no big deal.

Change-Id: Icbe09cd2f9b33bc58ab1efe7de293dea00236fec
pull/1923/head
Richard Fuchs 1 month ago
parent 1a837e6ab1
commit 9bd5670f89

@ -254,7 +254,7 @@ static void *thread_detach_func(void *d) {
dt->priority, strerror(errno));
}
media_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free, 64 * 65536);
media_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free);
#ifdef HAVE_LIBURING
if (rtpe_config.common.io_uring)
uring_thread_init();

@ -19,7 +19,6 @@
#include "xt_RTPENGINE.h"
#define PREFIX "/proc/rtpengine"
#define MMAP_PAGE_SIZE (4096 * 16)
struct kernel_interface kernel;
@ -58,13 +57,13 @@ static bool kernel_delete_table(unsigned int id) {
return kernel_action_table("del", id);
}
static void *kernel_alloc(size_t len) {
void *b = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, kernel.fd, 0);
static void *kernel_alloc(void) {
void *b = mmap(NULL, BUFFERPOOL_SHARD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, kernel.fd, 0);
assert(b != NULL && b != MAP_FAILED);
return b;
}
static void kernel_free(void *p, size_t len) {
munmap(p, len);
static void kernel_free(void *p) {
munmap(p, BUFFERPOOL_SHARD_SIZE);
}
static int kernel_open_table(unsigned int id) {
@ -144,7 +143,7 @@ bool kernel_setup_table(unsigned int id) {
kernel.table = id;
kernel.is_open = true;
shm_bufferpool = bufferpool_new2(kernel_alloc, kernel_free, MMAP_PAGE_SIZE);
shm_bufferpool = bufferpool_new(kernel_alloc, kernel_free);
return true;
}

@ -1458,7 +1458,7 @@ static void early_init(void) {
#ifdef WITH_TRANSCODING
static void clib_init(void) {
media_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free, 64 * 65536);
media_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free);
#ifdef HAVE_LIBURING
if (rtpe_config.common.io_uring)
uring_thread_init();
@ -1506,7 +1506,7 @@ static void kernel_setup(void) {
return;
fallback:
shm_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free, 4096); // fallback userspace bufferpool
shm_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free); // fallback userspace bufferpool
}

@ -3,12 +3,12 @@
#include <stdbool.h>
#include "obj.h"
static_assert((BUFFERPOOL_SHARD_SIZE & (BUFFERPOOL_SHARD_SIZE - 1)) == 0,
"BUFFERPOOL_SHARD_SIZE is not a power of two");
struct bufferpool {
void *(*alloc)(size_t);
void *(*alloc)(void);
void (*dealloc)(void *);
void (*dealloc2)(void *, size_t);
size_t shard_size;
size_t address_mask;
mutex_t lock;
GQueue empty_shards;
GQueue full_shards;
@ -21,7 +21,6 @@ struct bpool_shard {
void *buf; // actual head of buffer, given to free()
void *empty; // head of usable buffer, head == empty if empty
void *end;
size_t size;
void *head;
bool full;
unsigned int (*recycle)(void *);
@ -32,30 +31,16 @@ struct bpool_shard {
static rwlock_t bpool_shards_lock = RWLOCK_STATIC_INIT;
static GPtrArray *bpool_shards;
static struct bufferpool *bufferpool_new_common(void *(*alloc)(size_t), size_t shard_size) {
struct bufferpool *bufferpool_new(void *(*alloc)(void), void (*dealloc)(void *)) {
struct bufferpool *ret = g_new0(__typeof(*ret), 1);
ret->alloc = alloc;
ret->shard_size = shard_size;
ret->address_mask = shard_size - 1;
assert((ret->address_mask & shard_size) == 0); // must be a power of two
mutex_init(&ret->lock);
g_queue_init(&ret->empty_shards);
g_queue_init(&ret->full_shards);
return ret;
}
struct bufferpool *bufferpool_new(void *(*alloc)(size_t), void (*dealloc)(void *), size_t shard_size) {
struct bufferpool *ret = bufferpool_new_common(alloc, shard_size);
ret->dealloc = dealloc;
return ret;
}
struct bufferpool *bufferpool_new2(void *(*alloc)(size_t), void (*dealloc)(void *, size_t), size_t shard_size) {
struct bufferpool *ret = bufferpool_new_common(alloc, shard_size);
ret->dealloc2 = dealloc;
return ret;
}
// bufferpool is locked and shard is in "full" list but with zero refs
static void bufferpool_recycle(struct bpool_shard *shard) {
struct bufferpool *bp = shard->bp;
@ -74,13 +59,7 @@ static void bufferpool_recycle(struct bpool_shard *shard) {
static void bufferpool_dealloc(struct bpool_shard *shard) {
struct bufferpool *bp = shard->bp;
void *p = shard->buf;
size_t len = shard->size;
if (bp->dealloc)
bp->dealloc(p);
else
bp->dealloc2(p, len);
bp->dealloc(shard->buf);
}
// bufferpool is locked
@ -101,20 +80,19 @@ static int bpool_shards_sort(const void *A, const void *B) {
}
static struct bpool_shard *bufferpool_new_shard(struct bufferpool *bp) {
void *buf = bp->alloc(bp->shard_size);
void *buf = bp->alloc();
if (!buf)
return NULL;
// all bottom bits must be zero
assert(((size_t) buf & (bp->shard_size - 1)) == 0);
assert(((size_t) buf & BUFFERPOOL_BOTTOM_MASK) == 0);
struct bpool_shard *ret = g_new0(__typeof(*ret), 1);
ret->bp = bp;
ret->buf = buf;
ret->size = bp->shard_size;
ret->empty = buf;
ret->head = buf;
ret->end = buf + bp->shard_size;
ret->end = buf + BUFFERPOOL_SHARD_SIZE;
RWLOCK_W(&bpool_shards_lock);
@ -125,7 +103,7 @@ static struct bpool_shard *bufferpool_new_shard(struct bufferpool *bp) {
}
void *bufferpool_alloc(struct bufferpool *bp, size_t len) {
if (len > bp->shard_size)
if (len > BUFFERPOOL_SHARD_SIZE)
return NULL;
LOCK(&bp->lock);
@ -323,8 +301,8 @@ void bufferpool_cleanup(void) {
g_ptr_array_free(bpool_shards, true);
}
void *bufferpool_aligned_alloc(size_t len) {
void *m = aligned_alloc(len, len);
void *bufferpool_aligned_alloc(void) {
void *m = aligned_alloc(BUFFERPOOL_SHARD_SIZE, BUFFERPOOL_SHARD_SIZE);
assert(m != NULL);
return m;
}

@ -6,14 +6,18 @@
#define BUFFERPOOL_ALIGNMENT (sizeof(void *)) // bytes
#define BUFFERPOOL_ALIGN(x) (((x + BUFFERPOOL_ALIGNMENT - 1) / BUFFERPOOL_ALIGNMENT) * BUFFERPOOL_ALIGNMENT)
#define BUFFERPOOL_SHARD_SIZE (1LL<<24) // 16 MB, must be a power of two
#define BUFFERPOOL_OVERHEAD (0) // storage space not available
#define BUFFERPOOL_BOTTOM_MASK (BUFFERPOOL_SHARD_SIZE - 1)
struct bufferpool;
struct bpool_shard;
void bufferpool_init(void);
void bufferpool_cleanup(void);
struct bufferpool *bufferpool_new(void *(*alloc)(size_t), void (*dealloc)(void *), size_t shard_size);
struct bufferpool *bufferpool_new2(void *(*alloc)(size_t), void (*dealloc)(void *, size_t), size_t shard_size);
struct bufferpool *bufferpool_new(void *(*alloc)(void), void (*dealloc)(void *));
void bufferpool_destroy(struct bufferpool *);
void *bufferpool_alloc(struct bufferpool *bp, size_t len);
@ -30,7 +34,7 @@ INLINE void *bufferpool_alloc0(struct bufferpool *bp, size_t len) {
return ret;
}
void *bufferpool_aligned_alloc(size_t);
void *bufferpool_aligned_alloc(void);
void bufferpool_aligned_free(void *);
typedef char bp_char;

@ -144,7 +144,9 @@ struct poller *uring_poller_new(void) {
ret->evs = g_ptr_array_new();
ret->blocked = g_array_new(false, true, sizeof(char));
ret->bufferpool = bufferpool_new(g_malloc, g_free, BUFFER_SIZE * BUFFERS_COUNT);
static_assert(BUFFERPOOL_SHARD_SIZE - BUFFERPOOL_OVERHEAD >= BUFFER_SIZE * BUFFERS_COUNT,
"BUFFERPOOL_SHARD_SIZE too small");
ret->bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free);
for (int i = 0; i < BUFFER_POOLS; i++) {
ret->buffers[i] = g_new0(__typeof(*ret->buffers[i]), 1);
ret->buffers[i]->buf = bufferpool_reserve(ret->bufferpool, BUFFERS_COUNT,

@ -68,7 +68,7 @@ static void __assert_metrics_eq(stats_metric_q *q, const char *b, unsigned int l
int main(void) {
rtpe_common_config_ptr = &rtpe_config.common;
bufferpool_init();
shm_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free, 4096);
shm_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free);
endpoint_parse_any(&rtpe_config.graphite_ep, "1.2.3.4:4567");

@ -418,8 +418,8 @@ static void dtmf(const char *s) {
int main(void) {
rtpe_common_config_ptr = &rtpe_config.common;
bufferpool_init();
media_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free, 4096);
shm_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free, 4096);
media_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free);
shm_bufferpool = bufferpool_new(bufferpool_aligned_alloc, bufferpool_aligned_free);
unsigned long random_seed = 0;

Loading…
Cancel
Save