After Yahtzee and Exploding Kittens, the next game to get this treatment was Farkle. The result is go-farkle, which computes optimal play for the two-player game and will happily tell you that the roll you were about to bank is worth another throw.
The first two posts in this series were about collecting data: CPU and wall-clock samples from a signal handler, and heap samples from inside the allocator. Both produce a pile of stack traces with counts attached.
In Part 1 I wrote about sampling where a Python program spends its time. Memory usage is the other half of the question. Like time profiling, you can sample exhaustively (which is what the standard libarry tracemalloc does), but this is far too expensive to leave enabled in a production server. Unfortunately this means you often tend to enable it after you have a problem, on a process that no longer contains the interesting state.
I was working on a profiling system at work and became jealous of Go. The Go runtime has CPU and heap profilers built into the language. You can attach to a running production service, pull a profile over HTTP, and explore it with go tool pprof — flame graphs, call trees, diffs between two snapshots — without restarting anything or deciding in advance that today was the day you would need a profile.
in Games on Games, Game-theory, Go, Machine-learning
Over the holidays I played Exploding Kittens with my family for the first time. The player who draws the exploding cat loses unless they can defuse it; cards can skip turns, draw from the bottom of the deck, reveal the next few cards, shuffle the deck, or force a card to change hands. It is a pleasantly compact ruleset and can be played with almost any number of players. I lost, and in typical fashion, set out to solve the game. I call it AlphaCats.