Is pitchfork using too much memory?

Does anyone else see this? It’s a pretty modest forum in size and traffic. There are four pitchfork worker processes, it looks like one of them handles the great majority of incoming requests and is using more memory than the others. There’s lots of swap in use, and by deliberately respawning pitchfork this reduces considerably. So I conclude the pitchfork processes have a lot of cold pages presently swapped out.

This is after 20 days of operation, on a machine with 4G RAM and 4G swap.

It wouldn’t be good to run out of swap. It wouldn’t be good to find all that swap being paged back in, as might possibly happen when pitchfork eventually does a garbage collect.

Anyone else see anything similar? Please share machine config!

# ps aux | sort -n -k 4 | egrep pitchf\|MEM |tail
root     2167652  0.0  0.0   5912  1792 pts/0    S+   20:07   0:00 grep -E --color=auto pitchf|MEM
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1000       15094  0.0  0.2 497544 10988 ?        Sl   Jul28   0:17 pitchfork monitor - 
1000       15704  0.0  2.5 6799124 97836 ?       Sl   Jul28   1:00 pitchfork (gen:0) service - ready
1000       15097  0.0  4.8 6791252 189724 ?      Sl   Jul28   5:26 pitchfork (gen:0) mold - ready
1000       15959  0.0  8.1 6815508 319708 ?      Sl   Jul28  12:05 pitchfork (gen:0) worker[3] - requests: 6684, waiting
1000       15900  0.0  9.2 6864596 360696 ?      Sl   Jul28  17:43 pitchfork (gen:0) worker[2] - requests: 14756, waiting
1000       15795  0.1 10.3 6884756 405420 ?      Sl   Jul28  48:36 pitchfork (gen:0) worker[1] - requests: 97007, waiting
1000       15734  2.1 12.8 11299708 500120 ?     Sl   Jul28 637:50 pitchfork (gen:0) worker[0] - requests: 2229848, waiting

# free
               total        used        free      shared  buff/cache   available
Mem:         3904968     1874636       98840      678812     1931492     1160916
Swap:        4194288     1226600     2967688


# vmstat 5 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0 1226600 115820  65288 1866284    1    1    20    38    0    3  3  1 97  0  0
 0  0 1226600 113208  65296 1866296    0    0     0    14  411  478  1  1 98  0  0
 0  0 1226600 112956  65304 1866336    0    0     1    23  438  528  2  1 97  0  0
 0  0 1226600 112704  65308 1866360    0    0     1    31  518  603  5  1 94  0  0
 0  0 1226600 112704  65308 1866364    0    0     0    11  347  387  1  1 98  0  0

The vmstat output shows that there’s not presently any memory pressure - no paging activity. My concern is that there’s a danger, not that my installation is presently working poorly.

cpu0

In a more serious note, the one doing all the work has just 100MB RSS over the average? Looks normal to me, or am I missing something ?

I’d be interested to see the stats from a more busy forum. It seems that the cumulative number of requests is important, and mine is by no means very busy.

Yes, the RSS differences are relatively modest, but ranging from 300M to 500M there’s quite a difference in proportion.

More striking is the swap usage. Before recycling the pitchforks, I see

# free
               total        used        free      shared  buff/cache   available
Mem:         3904968     1888140       77308      679004     1939520     1147220
Swap:        4194288     1226344     2967944

and after

# free
               total        used        free      shared  buff/cache   available
Mem:         3904968     1486412     1422380      640744      996176     1587908
Swap:        4194288      309892     3884396

Looks to me like 1300M freed by recycling (difference of used+swap)

I don’t believe I saw this much swap needed when using unicorn: hence the title.

As I say, interested in seeing numbers from other instances.

It’s normal for one pitchfork process to take most of the load - other processes are only picked when the first one is busy. It’s also normal for memory to grow over time. Although it should eventually reach a steady state, once everything like caches/ruby-JIT are warmed up.

Here’s a graph from one of our production clusters, over a 7-day period. This tracks the single process with the most memory usage. Green-dotted lines indicate deploys (i.e. fresh starts of pitchfork):

So you can see, it does grow after initial launch, but then it settles at just under 1.4GB. This cluster is serving hundreds of sites, so perhaps not the best comparison in terms of numbers… but hopefully the visualisation of the growth is useful.

Looking at per-process RSS numbers doesn’t tell the whole story. Pitchfork is a “forking web server”. So it boots up the ‘mold’ process, and then all of the workers are forked from that with a copy-on-write memory pattern. So, while the RSS might show 500mb for worker[0], ~200mb of that is shared with the mold and all the other workers.

In the not-too-distant future we’re hoping to enable Pitchfork’s “reforking” feature. It periodically kills workers, and re-forks them from an already-warmed-up worker, so they share as much memory as possible over time. Some work needed to make sure that all our code is compatible with that kind of pattern though :crossed_fingers:

Useful visualisation, thanks. I wouldn’t say that had settled, but the growth rate isn’t as high as it has been.

The periodic reforking sounds like a great thing to bring it - if you could, please note it here when that lands.

Can you say anything about the green lines? I’m interested in when (if ever) the pitchforks do a garbage collect, what causes it and what the effect is while it’s doing it.

The green lines are when we deploy updates. Essentially: ./launcher rebuild app.

Ruby (and JS, which we run inside the Ruby processes via MiniRacer/v8) are constantly garbage-collecting while they’re running, and in response to signals from the operating system. So I don’t think there’s any large benefit to be gained from doing anything manually.

Thanks. I’d be interested to see how things work out in the long run - which won’t be evident on a server that’s being updated relatively often. In my case, I had 20 days, then I chose to get pitchfork to restart, which told me something but also reset the clock.