well-typed / grapesy

Native Haskell gRPC client and server based on `http2`
Other
31 stars 4 forks source link

Investigate memory behavior of many non-streaming connections #133

Open FinleyMcIlwaine opened 2 months ago

FinleyMcIlwaine commented 2 months ago

During stress testing, we discovered that the memory profile of opening many connections and executing a single non-streaming RPC call results in strange memory behavior, especially relative to executing many non-streaming calls on a single connection. In particular, we see some closures relating to HPACK slowly pile up before reaching a constant heap residency of anywhere between 2M and 18M. (Exactly what this heap residency is depends on the RTS sample rate, strangely, but that's another can of worms that grapesy probably doesn't need to care about.)

Screenshot 2024-04-10 at 11 48 02 AM

Each of the lines in the above chart marks 1000 new connections.

Screenshot 2024-04-10 at 11 48 54 AM

Thankfully, the memory complexity still appears constant, but this is nonetheless worth investigating to see if we can reduce the residency.

Contrast this against doing the same number of calls on a single connection:

Screenshot 2024-04-10 at 11 56 13 AM

Much lower and more consistent residency.

Reproduce

To reproduce, run the test-stress executable server and client:

cabal run test-stress -- server
cabal run test-stress -- client many-connections 10000 +RTS -s -l -olclient.eventlog -i0.01 -hi

Don't forget to enable -finfo-table-map -fdistinct-constructor-tables on at least grapesy and probably http2.