Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Work allocation
# frozen_string_literal: true
class WorkAllocation
# Runtime process allocations. Last reviewed: 24/9/2019
# Half a gig system allocation for agents and monitors and, unfortunately,
# a couple of deploy-time asset compiles due to dependencies. It's
# okay to push some processes into swap on smaller instances during
# deploy. Ideally we wouldn't compile on-instance at all.
OPS_MEMORY_ALLOWANCE = 512
# Our app processes currently hover around 300MiB RSS in production.
# Allow a little headroom because they sometimes crunch big imports/exports.
PROCESS_SIZE_ESTIMATE = 350
def initialize memory
@system_memory = to_megabytes memory
end
# Allocate one background job processor per available GiB
def job_worker_count
at_least_one available_memory >> 10
end
# Divvy up the rest for application servers
def app_server_count
at_least_one (memory_for_app_servers.fdiv PROCESS_SIZE_ESTIMATE).round
end
# Nginx is cheap and websockets elevate the demand.
# Run eight per app server.
def web_server_count
app_server_count << 3
end
private
attr_reader :system_memory
# Ohai, why can't you just give us integers?
def to_megabytes memory
case memory.to_s
when /\A([0-9]+)TB\z/; $1.to_i << 20
when /\A([0-9]+)GB\z/; $1.to_i << 10
when /\A([0-9]+)MB\z/; $1.to_i
when /\A([0-9]+)kB\z/; $1.to_i >> 10
when /\A([0-9]+)\z/; $1.to_i >> 20
else
raise ArgumentError, "invalid memory value #{memory.inspect}"
end
end
def at_least_one count
[count.to_i, 1].max
end
def available_memory
system_memory - OPS_MEMORY_ALLOWANCE
end
def memory_for_app_servers
available_memory - job_worker_count * PROCESS_SIZE_ESTIMATE
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment