use memory arena to optimize handing data to frontend

This commit is contained in:
itsmattkc 2024-11-15 16:52:19 -08:00
parent 410b002d99
commit 242386ea75
6 changed files with 103 additions and 15 deletions

View file

@ -30,6 +30,8 @@ void Backend::vanillaEventHandler()
emit vibrate(*event.data);
break;
}
vanilla_free_event(&event);
}
}

View file

@ -3,6 +3,7 @@
#include "gamepad.h"
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
@ -31,6 +32,10 @@ uint16_t PORT_AUD;
uint16_t PORT_HID;
uint16_t PORT_CMD;
#define EVENT_BUFFER_SIZE 65536
#define EVENT_BUFFER_ARENA_SIZE VANILLA_MAX_EVENT_COUNT * 2
uint8_t *EVENT_BUFFER_ARENA[EVENT_BUFFER_ARENA_SIZE] = {0};
void send_to_console(int fd, const void *data, size_t data_size, int port)
{
struct sockaddr_in address;
@ -38,11 +43,10 @@ void send_to_console(int fd, const void *data, size_t data_size, int port)
address.sin_addr.s_addr = SERVER_ADDRESS;
address.sin_port = htons((uint16_t) (port - 100));
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &address.sin_addr, ip, INET_ADDRSTRLEN);
ssize_t sent = sendto(fd, data, data_size, 0, (const struct sockaddr *) &address, sizeof(address));
if (sent == -1) {
char ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &address.sin_addr, ip, INET_ADDRSTRLEN);
print_info("Failed to send to Wii U socket: address: %s, fd: %d, port: %d, errno: %i", ip, fd, port - 100, errno);
}
}
@ -286,12 +290,19 @@ int is_stop_code(const char *data, size_t data_length)
int push_event(event_loop_t *loop, int type, const void *data, size_t size)
{
pthread_mutex_lock(&loop->mutex);
vanilla_event_t *ev = &loop->events[loop->new_index % VANILLA_MAX_EVENT_COUNT];
if (size <= sizeof(ev->data)) {
if (size <= EVENT_BUFFER_SIZE) {
assert(!ev->data);
ev->data = get_event_buffer();
if (!ev->data) {
print_info("OUT OF MEMORY FOR NEW EVENTS");
return VANILLA_ERROR;
}
ev->type = type;
memcpy(ev->data, data, size);
ev->size = size;
@ -300,13 +311,14 @@ int push_event(event_loop_t *loop, int type, const void *data, size_t size)
// Prevent rollover by skipping oldest event if necessary
if (loop->new_index > loop->used_index + VANILLA_MAX_EVENT_COUNT) {
vanilla_free_event(&loop->events[loop->used_index % VANILLA_MAX_EVENT_COUNT]);
print_info("SKIPPED EVENT TO PREVENT ROLLOVER (%lu > %lu + %lu)", loop->new_index, loop->used_index, VANILLA_MAX_EVENT_COUNT);
loop->used_index++;
}
pthread_cond_broadcast(&loop->waitcond);
} else {
print_info("FAILED TO PUSH EVENT: wanted %lu, only had %lu. This is a bug, please report to developers.\n", size, sizeof(ev->data));
print_info("FAILED TO PUSH EVENT: wanted %lu, only had %lu. This is a bug, please report to developers.\n", size, EVENT_BUFFER_SIZE);
}
pthread_mutex_unlock(&loop->mutex);
@ -330,9 +342,11 @@ int get_event(event_loop_t *loop, vanilla_event_t *event, int wait)
vanilla_event_t *pull_event = &loop->events[loop->used_index % VANILLA_MAX_EVENT_COUNT];
event->type = pull_event->type;
memcpy(event->data, pull_event->data, pull_event->size);
event->data = pull_event->data;
event->size = pull_event->size;
pull_event->data = NULL;
loop->used_index++;
ret = 1;
}
@ -342,3 +356,51 @@ int get_event(event_loop_t *loop, vanilla_event_t *event, int wait)
return ret;
}
void *get_event_buffer()
{
void *buf = NULL;
for (size_t i = 0; i < EVENT_BUFFER_ARENA_SIZE; i++) {
if (EVENT_BUFFER_ARENA[i]) {
buf = EVENT_BUFFER_ARENA[i];
EVENT_BUFFER_ARENA[i] = NULL;
break;
}
}
return buf;
}
void release_event_buffer(void *buffer)
{
for (size_t i = 0; i < EVENT_BUFFER_ARENA_SIZE; i++) {
if (!EVENT_BUFFER_ARENA[i]) {
EVENT_BUFFER_ARENA[i] = buffer;
break;
}
}
}
void init_event_buffer_arena()
{
for (size_t i = 0; i < EVENT_BUFFER_ARENA_SIZE; i++) {
if (!EVENT_BUFFER_ARENA[i]) {
EVENT_BUFFER_ARENA[i] = malloc(EVENT_BUFFER_SIZE);
} else {
print_info("CRITICAL: Buffer wasn't returned to the arena");
}
}
}
void free_event_buffer_arena()
{
for (size_t i = 0; i < EVENT_BUFFER_ARENA_SIZE; i++) {
if (EVENT_BUFFER_ARENA[i]) {
free(EVENT_BUFFER_ARENA[i]);
EVENT_BUFFER_ARENA[i] = NULL;
} else {
print_info("CRITICAL: Buffer wasn't returned to the arena");
}
}
}

View file

@ -42,4 +42,9 @@ int is_stop_code(const char *data, size_t data_length);
int push_event(event_loop_t *loop, int type, const void *data, size_t size);
int get_event(event_loop_t *loop, vanilla_event_t *event, int wait);
void init_event_buffer_arena();
void free_event_buffer_arena();
void *get_event_buffer();
void release_event_buffer(void *buffer);
#endif // VANILLA_GAMEPAD_H

View file

@ -30,9 +30,13 @@ void *start_gamepad(void *arg)
struct gamepad_data_t *data = (struct gamepad_data_t *) arg;
pthread_mutex_lock(&event_loop.mutex);
init_event_buffer_arena();
event_loop.active = 1;
event_loop.new_index = 0;
event_loop.used_index = 0;
for (int i = 0; i < VANILLA_MAX_EVENT_COUNT; i++) {
event_loop.events[i].data = NULL;
}
pthread_cond_broadcast(&event_loop.waitcond);
pthread_mutex_unlock(&event_loop.mutex);
@ -42,6 +46,7 @@ void *start_gamepad(void *arg)
pthread_mutex_lock(&event_loop.mutex);
event_loop.active = 0;
free_event_buffer_arena();
pthread_cond_broadcast(&event_loop.waitcond);
pthread_mutex_unlock(&event_loop.mutex);
@ -171,3 +176,11 @@ int vanilla_wait_event(vanilla_event_t *event)
{
return get_event(&event_loop, event, 1);
}
int vanilla_free_event(vanilla_event_t *event)
{
if (event->data) {
release_event_buffer(event->data);
event->data = NULL;
}
}

View file

@ -98,7 +98,7 @@ static const uint8_t VANILLA_PPS_PARAMS[] = {
typedef struct
{
int type;
uint8_t data[65536];
uint8_t *data;
size_t size;
} vanilla_event_t;
@ -110,6 +110,7 @@ int vanilla_sync(uint16_t code, uint32_t server_address);
int vanilla_poll_event(vanilla_event_t *event);
int vanilla_wait_event(vanilla_event_t *event);
int vanilla_free_event(vanilla_event_t *event);
/**
* Attempt to stop the current action

View file

@ -105,10 +105,12 @@ static SDL_mutex *decode_loop_mutex;
static SDL_cond *decode_loop_cond;
static int decode_loop_running = 0;
static int decode_pkt_ready = 0;
static vanilla_event_t decode_event;
static uint8_t decode_data[65536];
static size_t decode_size = 0;
int decode_loop(void *)
{
vanilla_event_t our_pkt;
uint8_t our_data[65536];
size_t our_data_size = 0;
SDL_LockMutex(decode_loop_mutex);
while (decode_loop_running) {
@ -116,12 +118,12 @@ int decode_loop(void *)
SDL_CondWait(decode_loop_cond, decode_loop_mutex);
}
our_pkt = decode_event;
decode_pkt_ready = 0;
memcpy(our_data, decode_data, decode_size);
our_data_size = decode_size;
SDL_UnlockMutex(decode_loop_mutex);
decode(our_pkt.data, our_pkt.size);
decode(our_data, decode_size);
SDL_LockMutex(decode_loop_mutex);
}
@ -153,7 +155,8 @@ int run_backend(void *data)
while (vanilla_wait_event(&event)) {
if (event.type == VANILLA_EVENT_VIDEO) {
SDL_LockMutex(decode_loop_mutex);
decode_event = event;
memcpy(decode_data, event.data, event.size);
decode_size = event.size;
decode_pkt_ready = 1;
SDL_CondBroadcast(decode_loop_cond);
SDL_UnlockMutex(decode_loop_mutex);
@ -167,6 +170,8 @@ int run_backend(void *data)
} else if (event.type == VANILLA_EVENT_VIBRATE) {
vibrate = event.data[0];
}
vanilla_free_event(&event);
}
SDL_LockMutex(decode_loop_mutex);