File tree Expand file tree Collapse file tree 4 files changed +58
-2
lines changed Expand file tree Collapse file tree 4 files changed +58
-2
lines changed Original file line number Diff line number Diff line change
1
+ #!/usr/bin/env ruby
2
+ # Instantiate about one process per X MiB of available memory, scaling up to as
3
+ # close to MAX_THREADS as possible while observing an upper bound based on the
4
+ # number of virtual/logical CPUs. If there are fewer processes than
5
+ # MAX_THREADS, add threads per process to reach MAX_THREADS.
6
+ require 'etc'
7
+
8
+ KB_PER_WORKER = 64 * 1_024 # average of peak PSS of single-threaded processes (watch smem -k)
9
+ MIN_WORKERS = 2
10
+ MAX_WORKERS_PER_VCPU = 1.25 # virtual/logical
11
+ MIN_THREADS_PER_WORKER = 1
12
+ MAX_THREADS = Integer ( ENV [ 'MAX_CONCURRENCY' ] || 256 )
13
+
14
+ def meminfo ( arg )
15
+ File . open ( '/proc/meminfo' ) do |f |
16
+ f . each_line do |line |
17
+ key , value = line . split ( /:\s +/ )
18
+ return value . split ( /\s +/ ) . first . to_i if key == arg
19
+ end
20
+ end
21
+
22
+ raise "Unable to find `#{ arg } ' in /proc/meminfo!"
23
+ end
24
+
25
+ def auto_tune
26
+ avail_mem = meminfo ( 'MemAvailable' ) * 0.8 - MAX_THREADS * 1_024
27
+
28
+ workers = [
29
+ [ ( 1.0 * avail_mem / KB_PER_WORKER ) . floor , MIN_WORKERS ] . max ,
30
+ [ ( Etc . nprocessors * MAX_WORKERS_PER_VCPU ) . ceil , MIN_WORKERS ] . max
31
+ ] . min
32
+
33
+ threads_per_worker = [
34
+ workers < MAX_THREADS ? ( 1.0 * MAX_THREADS / workers ) . ceil : -Float ::INFINITY ,
35
+ MIN_THREADS_PER_WORKER
36
+ ] . max
37
+
38
+ [ workers , threads_per_worker ]
39
+ end
40
+
41
+ p auto_tune if $PROGRAM_NAME == __FILE__
Original file line number Diff line number Diff line change
1
+ require_relative 'auto_tune'
2
+
3
+ # FWBM only... use the puma_auto_tune gem in production!
4
+ num_workers , num_threads = auto_tune
5
+
6
+ workers num_workers
7
+ threads num_threads , num_threads
8
+ # Use the `preload_app!` method when specifying a `workers` number.
9
+ # This directive tells Puma to first boot the application and load code
10
+ # before forking the application. This takes advantage of Copy On Write
11
+ # process behavior so workers use less memory.
12
+ #
13
+ preload_app!
Original file line number Diff line number Diff line change 1
- worker_processes 8
1
+ require_relative 'auto_tune'
2
+
3
+ worker_processes , = auto_tune
2
4
listen "/tmp/unicorn.sock" , :backlog => 4096
3
5
4
6
preload_app true
Original file line number Diff line number Diff line change @@ -10,4 +10,4 @@ RUN bundle install --jobs=4 --gemfile=/grape/Gemfile --path=/grape/grape/bundle
10
10
11
11
EXPOSE 8080
12
12
13
- CMD bundle exec puma -t 8:32 -w 8 --preload -b tcp://0.0.0.0:8080 -e production
13
+ CMD bundle exec puma -C config/puma.rb -b tcp://0.0.0.0:8080 -e production
You can’t perform that action at this time.
0 commit comments