Skip to content

Official pursuit server performance is not good #482

@flip111

Description

@flip111

Problem

Since a few weeks, maybe even months i'm see slow results and frequent 502 Bad Gateway not available. I asked on discord and other people also have problems. I think nobody made an issue before because if you just wait a bit and try again then often is ok. Though this issue could be related #480

Findings

I downloaded the source code and tested it under load. What i see is this

 .stack-work/dist/x86_64-linux/ghc-9.2.5/build/pursuit/pursuit +RTS -p                                                                                                                                                                                                   [0:22:11]
[Warn] No GitHub auth token configured (environment variable is: PURSUIT_GITHUB_AUTH_TOKEN)
[Warn] Requests to the GitHub API will be performed with no authentication.
[Warn] This will probably result in rate limiting.
Starting in development mode
PURSUIT_CLIENT_SESSION_KEY=Ymb0FVgpNlybkO5MxbHL4DnbZkZ2zJrDHxjcS3Sn4TlquQJv23rPGr5oxNqoVzhDWsw7hZ3YERy083YCXDokhZrguj1VPY2A51UB+0/Biy89PJViBDsxiqjbrKc5G+LB
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
GET /
  Accept:
  Status: 500 Internal Server Error 0.058559736s
GET /
  Accept:
  Status: 500 Internal Server Error 0.006288454s
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
GET /
  Accept:
  Status: 500 Internal Server Error 0.006520935s
03/Dec/2023:00:23:37 +0100 [Error#yesod-core] ./data/cache//index.html: withBinaryFile: resource busy (file is locked) @(yesod-core-1.6.24.0-9BHxG0hJFr59B2j5jcLrfq:Yesod.Core.Class.Yesod src/Yesod/Core/Class/Yesod.hs:705:6)
<...snip....>

Investigation & thoughts

This is the only place in the source code i found "index.html" https://github.com/purescript/pursuit/blob/master/src/Handler/Caching.hs#L65-L69

when i look where the functions cacheHtml and cacheHtmlConditional are used i see function names like

  • getHelpR
  • getHelpAuthorsR
  • getHelpUsersR
  • getHomeR
  • getPackageVersionR
  • getPackageVersionModuleDocsR

Which i think are all different pages on pursuit.

I don't understand this caching mechanism. Why would you cache to the same file for different pages?

When i let pursuit run in single threaded mode with +RTS -N1 i still get contention over the index.html but far less. I guess yesod still has some form of concurrency going on as time division multiplexing several requests on a single thread.

Performance on server

The official pursuit server is also struggling a lot (though it could be underspecced i don't know) @JordanMartinez perhaps you could have a look over a longer time window than 7 days?
cpu
memory

Reproduction

To reproduce load testing and profile deeper in time spend per function and memory allocated per function i used the following.

wrk2.dockerfile

FROM alpine
WORKDIR /wrk2
RUN apk add --no-cache git openssh make gcc musl-dev libressl-dev zlib-dev && \
    git clone https://github.com/giltene/wrk2.git /wrk2 && \
    make -j$(nproc)
ENTRYPOINT ["./wrk"]

profile_memory.sh

#!/usr/bin/env bash

TIME=60

docker build -t wrk2 --file wrk2.dockerfile .

stack build --profile
# stack exec pursuit --RTS -- +RTS -p & # didn't work
.stack-work/dist/x86_64-linux/ghc-9.2.5/build/pursuit/pursuit +RTS -p -N1 &
RETVAL=$?
PID=$!
docker run --rm --name wrk2 --network="host" wrk2 --rate 10 --duration ${TIME}s --threads $(nproc) --connections 400 --latency  http://localhost:3000
kill -INT $PID
sleep 1
profiteur pursuit.prof
xdg-open pursuit.prof.html

For the last two lines you need to install this tool https://github.com/jaspervdj/profiteur (which i recommend). Otherwise remove the the last two lines. When you open the html double click with your mouse on the big color area a lot of times to drill down quickly.


@hdgarrood do you have any idea what is happening here?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions