`String -> int` function

Background:

I’ve set up some remote builders for use by a group of people, and it works pretty well. I’d like to achieve two additional goals with this setup:

  1. The machines are semi-equally loaded. This is to make sure each job has the maximum amount of resources.
  2. Builds from a single person all go to the same machine as long as that machine has capacity. This is to make sure that jobs reuse the local Nix cache as much as possible, since a single user’s builds are probably going to be pretty similar to each other.

I couldn’t find some built-in way to achieve this, so I’m thinking of a hack: Since each user has a unique SSH username, and each person’s machine is configured to connect to all the builders using that username, I can

  1. convert the username to a number N,
  2. convert the hostname to a number M, and finally
  3. set nix.buildMachines.*.speedFactor to N×M (possibly modulo X).

For example, nix.buildMachines.0.speedFactor might be 1004 for Alice, 1234 for Bob, and 1345 for Charlie.

tl;dr: Is there some easy way to convert a string to a number (possibly including modulo, to avoid overflow), short of splitting the string into characters, mapping each to an integer, creating some giant base-[however many characters are allowed in a username or hostname] number, and doing modulo on that?

Alternatively, is there a better way to achieve load balancing and “personal favourites” with remote builders?

1 Like
nix-repl> builtins.fromJSON "123"
123

nix-repl> lib.toIntBase10 "10237"
10237

Pick whatever works best.

EDIT: actually it seems the latter uses fromJSON underneath :slight_smile: and is a bit more robust to e.g. spaces.

I meant an arbitrary string, not a numeric one.

No, and writing your own would be inefficient at best (and x-y).

maybe combine

and

https://teu5us.github.io/nix-lib.html#builtins.hashstring

and then parse with the aforementioned fromJSON function?

1 Like

Thank you for the tips! Ended up with a blog post since the code base I’m using it in is not public.

2 Likes

Great, I’m glad it worked!