summaryrefslogtreecommitdiff
path: root/src/trackerlogic.h
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-11-07 19:39:01 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-11-07 19:39:01 +0100
commit589cb500fa5a6df13fa9634d0071922ec11fce17 (patch)
treefa5fc07d6d13d7b241d884441d3d22c1d0189d87 /src/trackerlogic.h
parent1e7248b330bde4c70528ccf91535391e19294dc3 (diff)
Unify the peerlists for v4 and v6
This commit finishes what started with unifying v4 and v6 trackers, from then on, torrents carried a peer list per family, with obvious redundancies. With the race to save memory, these became burdening enough that now these peerlist pointers have been moved into a single struct, holding both v4 and v6 peers in their respective ot_vectors, so the per- torrent cost shrunk by another pointer's size. Each peerlist also lost its peer count cache, as in most cases, it's trivial to load it directly from the ot_vector's entry count. The seed counts that were kept per family only to be aggregated later for every consumer, are also merged now. Total savings depend on the tracker's actual load. In some corner cases, where only one address family dominates the torrents, we actually use a few bytes more in the ot_vector for the absent family, but even that mostly becomes noise: before it actually adds to the memory load, the peer payload will be the deciding factor. Most wins are on what often is experienced on trackers: A long tail of abandoned torrents now needs eight fewer bytes, slipping into a smaller allocation unit on glibc's allocator.
Diffstat (limited to 'src/trackerlogic.h')
-rw-r--r--src/trackerlogic.h39
1 files changed, 27 insertions, 12 deletions
diff --git a/src/trackerlogic.h b/src/trackerlogic.h
index c4b7774..dd8a48c 100644
--- a/src/trackerlogic.h
+++ b/src/trackerlogic.h
@@ -170,26 +170,40 @@ struct ot_peerlist;
170typedef struct ot_peerlist ot_peerlist; 170typedef struct ot_peerlist ot_peerlist;
171typedef struct { 171typedef struct {
172 ot_hash hash; 172 ot_hash hash;
173 ot_peerlist *peer_list6; /* NULL until the torrent has a v6 peer */ 173 ot_peerlist *peer_list; /* NULL until the torrent has a peer in either family */
174 ot_peerlist *peer_list4; /* NULL until the torrent has a v4 peer */ 174 uint32_t base; /* epoch minutes, when the torrent was last cleaned */
175 uint32_t base; /* minutes, when the torrent was last cleaned */ 175 uint32_t down_count; /* completed events */
176 uint32_t down_count; /* completed events, summed over both families */
177} ot_torrent; 176} ot_torrent;
178 177
179#include "ot_vector.h" 178#include "ot_vector.h"
180 179
181struct ot_peerlist { 180struct ot_peerlist {
182 uint32_t seed_count; 181 uint32_t seed_count;
183 uint32_t peer_count; 182 /* each family's peers: a normal vector, or a pointer to ot_vector[] buckets
184 /* normal peers vector or 183 when data != NULL and space == 0 (size then holds the bucket count) */
185 pointer to ot_vector[32] buckets if data != NULL and space == 0 184 ot_vector peers6;
186 */ 185 ot_vector peers4;
187 ot_vector peers;
188}; 186};
189#define OT_PEERLIST_HASBUCKETS(peer_list) ((peer_list)->peers.size > (peer_list)->peers.space)
190 187
191static inline uint32_t peerlist_peer_count(const ot_peerlist *peer_list) { return peer_list ? peer_list->peer_count : 0; } 188/* A peer vector becomes a bucket list of peer vectors, marker is size > space (usually 0) */
192static inline uint32_t peerlist_seed_count(const ot_peerlist *peer_list) { return peer_list ? peer_list->seed_count : 0; } 189#define OT_VECTOR_HASBUCKETS(v) ((v)->size > (v)->space)
190
191/* Peers in one family: a plain vector's size is the count, a bucket list's is
192 the sum of its buckets. O(1) for the small torrents that dominate a table. */
193static inline size_t vector_peer_count(const ot_vector *v) {
194 const ot_vector *b;
195 size_t n, total = 0;
196 if (!OT_VECTOR_HASBUCKETS(v))
197 return v->size;
198 b = (const ot_vector *)v->data;
199 for (n = 0; n < v->size; ++n)
200 total += b[n].size;
201 return total;
202}
203static inline size_t torrent_peer_count(const ot_torrent *t) {
204 return t->peer_list ? vector_peer_count(&t->peer_list->peers6) + vector_peer_count(&t->peer_list->peers4) : 0;
205}
206static inline uint32_t torrent_seed_count(const ot_torrent *t) { return t->peer_list ? t->peer_list->seed_count : 0; }
193 207
194/* The http replies the tracker counts when it has to refuse a request. */ 208/* The http replies the tracker counts when it has to refuse a request. */
195enum { 209enum {
@@ -314,5 +328,6 @@ void iterate_all_torrents(int (*for_each)(ot_torrent *torrent, uintptr_t data),
314 328
315/* Helper, before it moves to its own object */ 329/* Helper, before it moves to its own object */
316void free_peerlist(ot_peerlist *peer_list); 330void free_peerlist(ot_peerlist *peer_list);
331void free_peer_vector(ot_vector *peer_vector);
317 332
318#endif 333#endif