-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
cpu_spin.rb
39 lines (31 loc) · 1.29 KB
/
cpu_spin.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# call with "GET /cpu/<d> HTTP/1.1\r\n\r\n", where <d> is the number of
# milliseconds to spin CPU, returns process pid
# configure `wait_for_less_busy_workers` based on ENV, default `true`
wait_for_less_busy_worker ENV.fetch('WAIT_FOR_LESS_BUSY_WORKERS', 'true') == 'true'
def cpu_threadtime
# Not all OS kernels are supporting `Process::CLOCK_THREAD_CPUTIME_ID`
# Refer: https://gitlab.com/gitlab-org/gitlab/issues/30567#note_221765627
return unless defined?(Process::CLOCK_THREAD_CPUTIME_ID)
Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID, :float_second)
end
def rand_for(duration_s)
end_time = cpu_threadtime + duration_s
rand while cpu_threadtime < end_time
end
app do |env|
duration_ms = (env['REQUEST_PATH'][/\/cpu\/(\d.*)/,1] || '1000').to_f
# This simulates an interleaved workload
# When thread is 50% free, and 50% busy with Ruby
#
# Another request might be picked during the `sleep`
# But, then it would compete with another request during
# `rand_for` execution
start_time = cpu_threadtime
expected_end_time = cpu_threadtime + duration_ms / 1000.0
while cpu_threadtime < expected_end_time do
sleep(0.01)
rand_for(0.01)
end
end_time = cpu_threadtime - start_time
[200, {"Content-Type" => "text/plain"}, ["Run for #{end_time} #{Process.pid}"]]
end