Hi Anthony, On Tue, Mar 12, 2024 at 07:10:42PM -0400, Anthony Deschamps wrote: > Hi Willy, > > Thanks for the feedback. I had been testing with smaller numbers of > servers (usually between 4 and 32) so I hadn't noticed the performance > impact.
Not surprised. I'm used to testing with some extreme setups for knowing such exist in field (more than 1000 servers in a single backend were already reported for example). > Here's an updated patch (as an attachment, until I figure out how > to make sure things are formatted correctly!) that should address that. Thanks. It's not a problem attached this way because my mailer still recognizes it as text and inlines it when responding, so that doesn't alter my ability to comment. > I added a "lb_server_key" to the server struct. I moved most of the hashing > logic that I previously had in "chash_compute_node_key" into a new function, > "chash_compute_server_key", and I store that value; nodes only need to be > removed and reinserted if this value changes. To compute a node key, I just > combine the server key with a hash of node_index. I considered using > XXH32_round to do this, but that looks like it's intended to be an internal > function, so I inlined something similar instead. You could always decide to combine an existing hash with another value, or combine one 32-bit key with a 32-bit index and apply a 64-bit hash, but I think that's fine this way. > Hopefully this all works. Thanks for taking the time to work through this, and > please let me know if there's anything else to address. I just got this: src/lb_chash.c: In function 'chash_compute_server_key': src/lb_chash.c:115:4: error: a label can only be part of a statement and a declaration is not a statement compilation terminated due to -Wfatal-errors. That's because of this: > + switch (hash_key) { > + case SRV_HASH_KEY_ADDR_PORT: > + case SRV_HASH_KEY_ADDR: > + switch (srv_addr.family) { > + case AF_INET: > + u32 addr_key = full_hash(srv_addr.addr.v4.s_addr); Here that's a declaration after a statement ("case" not being considered as the beginning of a block since you can pretty well fall through from a previous one). I'll adjust it while merging. I had a concern about the hashing function which seems to reduce the input key space, and indeed it does, it reduces 4294967296 server keys to only 2948667289 (68.65 %): > + key ^= addr_key + 0x9e3779b9 + (key << 6) + (key >> 2); Not critical but it would be better if we can avoid this loss. I tried with the full_hash() function and it preserves all output keys. So I think you should instead use: key = full_hash(add_key); and chash_compute_node_key() could then simply be achieved this way: static inline u32 chash_compute_node_key(struct server *s, unsigned node_index) { return full_hash(s->lb_server_key + node_index); } Other than that, I'm OK with the rest. Thanks! Willy