diff options
| author | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-31 15:59:41 +0100 |
|---|---|---|
| committer | Dirk Engling <erdgeist@erdgeist.org> | 2026-10-31 15:59:41 +0100 |
| commit | 4d030871c004c917458b5e1c296edcfc689a2e66 (patch) | |
| tree | c6c057e47a17d8b03ea28a611ff029d950acfa8c /trackerlogic.c | |
| parent | 440cfeee71829308fa1cc9b5aef63beb7ab756dc (diff) | |
Make tcp worker multithreaded, too
This shamelessly steals the model established in the UDP workers, i.e.
if the kernel is able to bind multiple listening sockets to the same
endpoint, we will share them across threads. If it can't, all threads
will accept on the same socket.
The fast path handles most of the connections, only the rare case of
no data yet on the socket is offloaded to the slow path (which used to
be the mainloop) for completion. This scales nicely, as the higher the
load is, the higher chances are that an accept happens only after the
network roundtrip to the peer completes, leading to more connections
that already have data waiting for us.
We also consolidate the workstruct init and deinit code, preparation
for later unifying all thread state structs for all protocols (mca,
udc and tcp).
The config file gains a per tcp connection worker count and some docs
explaining what this knob buys and costs, nudging the user to either
keep it 0 or dial it up to at least 2.
Diffstat (limited to 'trackerlogic.c')
| -rw-r--r-- | trackerlogic.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/trackerlogic.c b/trackerlogic.c index 477c4a6..fc0fa56 100644 --- a/trackerlogic.c +++ b/trackerlogic.c | |||
| @@ -567,6 +567,35 @@ void trackerlogic_init(void) { | |||
| 567 | stats_init(); | 567 | stats_init(); |
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | int workstruct_init(struct ot_workstruct *ws) { | ||
| 571 | memset(ws, 0, sizeof(*ws)); | ||
| 572 | ws->inbuf = malloc(G_INBUF_SIZE); | ||
| 573 | ws->outbuf = malloc(G_OUTBUF_SIZE); | ||
| 574 | #ifdef _DEBUG_HTTPERROR | ||
| 575 | ws->debugbuf = malloc(G_DEBUGBUF_SIZE); | ||
| 576 | #endif | ||
| 577 | if (!ws->inbuf || !ws->outbuf) | ||
| 578 | return -1; | ||
| 579 | |||
| 580 | /* Picking which peers to hand out starts here, so two workers seeded alike | ||
| 581 | would hand out alike */ | ||
| 582 | random_bytes(ws->rand48_state, sizeof(ws->rand48_state)); | ||
| 583 | |||
| 584 | stats_counters_register(ws); | ||
| 585 | return 0; | ||
| 586 | } | ||
| 587 | |||
| 588 | void workstruct_deinit(struct ot_workstruct *ws) { | ||
| 589 | /* The tally goes to the global before this struct goes out of scope */ | ||
| 590 | stats_counters_retire(ws); | ||
| 591 | |||
| 592 | free(ws->inbuf); | ||
| 593 | free(ws->outbuf); | ||
| 594 | #ifdef _DEBUG_HTTPERROR | ||
| 595 | free(ws->debugbuf); | ||
| 596 | #endif | ||
| 597 | } | ||
| 598 | |||
| 570 | void trackerlogic_deinit(void) { | 599 | void trackerlogic_deinit(void) { |
| 571 | int delta_torrentcount = 0; | 600 | int delta_torrentcount = 0; |
| 572 | size_t bucket, j; | 601 | size_t bucket, j; |
