summaryrefslogtreecommitdiff
path: root/opentracker.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-28 17:08:17 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-10-28 17:08:17 +0100
commitf3f640b6bcf10ba463fc81cec97cfa212c520cfe (patch)
tree94341752815b6b2d4c3a931be9b90c2c0f435baf /opentracker.c
parent18fcb27ec91f27789270550a2a005cb773bf2fe0 (diff)
Performance improvement, where it works: Let different udp worker threads have their own socket
Diffstat (limited to 'opentracker.c')
-rw-r--r--opentracker.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/opentracker.c b/opentracker.c
index a546fc5..f579b92 100644
--- a/opentracker.c
+++ b/opentracker.c
@@ -320,8 +320,17 @@ static void *server_mainloop(void *args) {
320} 320}
321 321
322 322
323/* A group of sockets sharing one address only spreads datagrams if every
324 member asked for it before binding, the first one included, so whether
325 this entry will have workers has to be known here. */
326static socket_sharing listen_sharing_for(const ot_listen *entry) {
327 if (entry->proto == FLAG_UDP && entry->workers > 1 && socket_can_balance())
328 return SOCKET_BALANCED;
329 return entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE;
330}
331
323static void listen_bind_one(ot_listen *entry) { 332static void listen_bind_one(ot_listen *entry) {
324 socket_sharing sharing = entry->shared ? SOCKET_SHARED : SOCKET_EXCLUSIVE; 333 socket_sharing sharing = listen_sharing_for(entry);
325 334
326#ifdef _DEBUG 335#ifdef _DEBUG
327 { 336 {
@@ -370,6 +379,10 @@ static void listen_bind_all(void) {
370 listen_bind_one(entries + i); 379 listen_bind_one(entries + i);
371} 380}
372 381
382/* The socket the event loop was using becomes the first worker's. Where the
383 kernel spreads datagrams, every further worker binds one of its own, so
384 none of them share a receive queue.
385 All others read from the first */
373static void listen_start_udp_workers(void) { 386static void listen_start_udp_workers(void) {
374 size_t count, i; 387 size_t count, i;
375 ot_listen *entries = config_listen_entries(&count); 388 ot_listen *entries = config_listen_entries(&count);
@@ -377,14 +390,30 @@ static void listen_start_udp_workers(void) {
377 udp_init(); 390 udp_init();
378 391
379 for (i = 0; i < count; ++i) { 392 for (i = 0; i < count; ++i) {
380 ot_listen *entry = entries + i; 393 ot_listen *entry = entries + i;
394 int balance = listen_sharing_for(entry) == SOCKET_BALANCED;
395 int worker;
381 396
382 if (entry->proto != FLAG_UDP || entry->workers <= 0) 397 if (entry->proto != FLAG_UDP || entry->workers <= 0)
383 continue; 398 continue;
384 399
385 socket_set_blocking((int)entry->sock, 1); 400 socket_set_blocking((int)entry->sock, 1);
386 event_del((int)entry->sock); 401 event_del((int)entry->sock);
387 udp_workers_install(entry->sock, (unsigned int)entry->workers); 402 udp_worker_install(entry->sock);
403
404 for (worker = 1; worker < entry->workers; ++worker) {
405 int64_t sock = entry->sock;
406
407 if (balance) {
408 sock = socket_udp_bind(entry->ip, entry->port, SOCKET_BALANCED);
409 if (sock == -1) {
410 fprintf(stderr, "Warning: could not bind another socket for udp worker %d: %s. Sharing the first instead.\n", worker, strerror(errno));
411 sock = entry->sock;
412 } else
413 socket_set_blocking((int)sock, 1);
414 }
415 udp_worker_install(sock);
416 }
388 } 417 }
389} 418}
390 419