#Avoiding stateful process bottlenecks

1 messages Β· Page 1 of 1 (latest)

edgy zodiac
#

I'm currently working on a server-side chess game to get a hang of Gleam, and I was wondering how to get around a possible bottleneck. The idea is that through HTTP requests a client can change the state of a chess game. The server can run multiple chess games simultaneously.

A client can create a new game by POSTing to /new, and then the a GameManager actor pushes a new Game to it's stack of games. Now if I understand correctly that's a hypothetical bottleneck, because if a lot of games get created at the same time, they all have to wait for this single GameManager actor to push to the stack. And then later on, if they POST a /move which moves a piece, we'd first have to go through the GameManager to request the current state of the game and then alter it, and push it again.

Is the Erlang ETS something that could solve this? Is there a gleam_ets package (couldn't find any)? Or are there other ways?

Btw I understand that with gleam_cowboy, every HTTP request is handled in a new process, is that true? If so, I guess you could stay in that process and request the game state through ETS and alter it, without going through a "bottleneck process"?

Quite new to Erlang/Gleam, sorry if something's obvious πŸ˜…

fringe birch
#

I think a normal way to design this system is to have one process per game

#

As games don't interact with each other it's very natural to shard the workload by them

#

Generally in OTP you don't want to think the conventional programming way of having a single worker (a thread, a process) managing multiple things while using a mutable cache (ETS) to improve performance, rather you want to split the workload as much as possible

#

It also makes the code much simpler as you only need to write code to manage 1 game at a time rather than multiple, and then you add a layer to manage many instances of the game logic process

#

So when a new game is started a new game process would be created, and the pid of that process would be registered in some fashion

#

When a request comes in you'd look up the pid for that game and then send a message to that process

edgy zodiac
#

Ah yes sorry I wasn't clear, indeed I was planning on creating a process per game. I guess my question is, when there's an HTTP request to alter game state, how can I go from the HTTP requests' process to the game process? How can it find the correct process to send messages to?

fringe birch
#

Ah right!

#

You'll want a registry, there are lots of them

#

There's a built in one called global, or there's the Elixir Registry

#

Neither will give you type safe message sending though

#

Another option is a process that just holds a map of strings to subjects/pids

#

(be sure to monitor the game processes so this registry can remove the processes from the state when they shut down)

#

I wouldn't worry about performance optimisations up front. Wait until you start to have performance issues and then use tools like the observer to identify where the bottlenecks are

edgy zodiac
#

Ahh interesting! Yeah registry seems to be what I'm looking for πŸ˜„ Noone's made a type-safe Gleam process registry yet?

fringe birch
#

Not yet

edgy zodiac
edgy zodiac
fringe birch
#

Have you run load tests and verified that it's a bottleneck?

#

If not, then you don't know it is one

edgy zodiac
#

Ha no it's purely imagined at the moment

fringe birch
#

I wouldn't worry then πŸ™‚

#

Optimisation done anywhere but the bottleneck is time wasted

edgy zodiac
#

Yeah true! So for now just having a process that holds pids is preferred in Gleam? Since the registries are not type-safe?

fringe birch
#

Registries can be type safe, but one has not been published

#

A registry is just a process that holds pids and monitors them for when they exit generally

edgy zodiac
#

Ah yeah okay, doesn't sound very different then πŸ˜„

fringe birch
#

Different ones have slightly different features, but yeah that's it mostly

#

global is designed to work across an entire cluster

#

Elixir's registry has some pubsub stuff

edgy zodiac
#

Ah I see, well thanks for all the help!

dusk trout
#

Just for the mental exercise:

Idk about all the otp stuff, but there are lots of ways to model the state of a chess game πŸ™‚ You could have a concept of a board and pieces, or a list of pieces and locations, or just a list of moves. Maybe there’s a model that works best for distributing πŸ™‚ I would look for prior art tbh, and see how much state you could actually just be passing around in the messages instead πŸ™‚

But for any real task I agree 100% with @fringe birch about the premature optimization stuff

edgy zodiac
#

Yeah interesting stuff! Currently I model the state as squares that are occupied by a Option(Piece). The idea is that the server would send the full state for each move, to allow the client to be "dumb" and just render the board. The client can check if a move is valid by just sending a move and the server returns just true/false (I suppose this is nice for message passing), and the client can also submit a real move to do, and if it's allowed, the server would send the full new board state

dusk trout
edgy zodiac
#

Ha yes it definitely could, but I'm trying out a system where all game logic happens intentionally server-side, as an experiment for future projects

#

Basically the server would assume a client cannot be trusted, and it would allow for an open-source game to have multiple clients for the same game, while still being fair (since no client knows more than any other)

#

For example with the chess, someone could make a fancy 3D one or a terminal one

pale badger
#

you should do both, check on client for convenience and on server for correctness

edgy zodiac
#

Yeah I'm just prototyping doing it server-only so there's no logic duplication, with the chess game, the client can still check with the server if a move is valid before submitting one, for convenience

fringe birch
#

Or use Gleam for the frontend and share code!

edgy zodiac
#

Also an option πŸ˜„

quiet fractal