Skip to content

Instantly share code, notes, and snippets.

@cgrand
Created March 15, 2018 15:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgrand/8a57d5761d2c5c5ab5dbec25d5d0c823 to your computer and use it in GitHub Desktop.
Save cgrand/8a57d5761d2c5c5ab5dbec25d5d0c823 to your computer and use it in GitHub Desktop.
(defn lambda-model
"Crude model. rps is requests per second, len is a function that returns the
execution length in seconds, until is the number of seconds to run the simulation,
spawn is a function returning the number of ping sub requests, duty is the max age
for a container, keep-alive is the number of seconds before decommissioning a
container.
Returns a map with: the number of user perceived cold starts and the number of
billable seconds."
[{:keys [rps len until spawn duty keep-alive]
:or {rps 10
len (constantly 1)
spawn (constantly 0)
duty (* 4 60 60)
keep-alive (* 30 60)
until (* 24 60 60)}}]
(let [n (Math/floor (* 0.1 rps))
pn+1 (- (* 0.1 rps) n)]
(loop [t 0.0 pings 0 containers nil stats {:s 0 :user-colds 0}]
(if (< t until)
(let [containers (into #{}
(comp
(remove #(and (<= (:end %) t)
(< (+ (:boot %) duty) t)))
(remove #(and (<= (:end %) t)
(< (+ (:end %) keep-alive) t))))
containers)
runnables (sort-by :end > (filter #(<= (:end %) t) containers)) ; lru
reqs (cond-> n (< (rand) pn+1) inc) ; not probabilistic enough
m (+ reqs pings)
next-pings (reduce + (repeatedly reqs spawn))
warms (take m runnables)
others (reduce disj containers warms)
colds (for [id (range 0 (- m (count warms)))]
{:boot t :end t
:id id})
ready (shuffle (concat warms colds))
started (-> []
(into (map #(assoc % :end (+ t (len)))) (take reqs ready))
(into (map #(assoc % :end (+ t 0.1))) (drop reqs ready)))
s (transduce (map #(- (:end %) t)) + started)
containers (into others started)
user-colds (count (filter #(= (:end %) (:boot %)) (take reqs ready)))]
(recur (+ t 0.1) next-pings containers
(-> stats (update :user-colds + user-colds) (update :s + s))))
stats))))
=> (lambda-model {:until (* 24 3600)
:len #(+ 0.8 (rand))
:rps 5})
{:s 561520.3102497417, :user-colds 98}
; with one "ping" generated for 50% of user requests
=> (lambda-model {:until (* 24 3600)
:len #(+ 0.8 (rand))
:spawn #(if (< (rand) 0.5) 1 0)
:rps 5})
{:s 582463.0752570062, :user-colds 54}
; the nuber of perceived cold starts is almost divided by 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment