2019-07-16 16:10:44 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Gitlab
|
|
|
|
# Chaos methods for GitLab.
|
|
|
|
# See https://docs.gitlab.com/ee/development/chaos_endpoints.html for more details.
|
|
|
|
class Chaos
|
|
|
|
# leak_mem will retain the specified amount of memory and sleep.
|
|
|
|
# On return, the memory will be released.
|
|
|
|
def self.leak_mem(memory_mb, duration_s)
|
|
|
|
start_time = Time.now
|
|
|
|
|
|
|
|
retainer = []
|
|
|
|
# Add `n` 1mb chunks of memory to the retainer array
|
|
|
|
memory_mb.times { retainer << "x" * 1.megabyte }
|
|
|
|
|
|
|
|
duration_left = [start_time + duration_s - Time.now, 0].max
|
|
|
|
Kernel.sleep(duration_left)
|
|
|
|
end
|
|
|
|
|
|
|
|
# cpu_spin will consume all CPU on a single core for the specified duration
|
|
|
|
def self.cpu_spin(duration_s)
|
2019-11-20 10:06:39 -05:00
|
|
|
return unless Gitlab::Metrics::System.thread_cpu_time
|
|
|
|
|
|
|
|
expected_end_time = Gitlab::Metrics::System.thread_cpu_time + duration_s
|
2019-07-16 16:10:44 -04:00
|
|
|
|
2019-11-20 10:06:39 -05:00
|
|
|
rand while Gitlab::Metrics::System.thread_cpu_time < expected_end_time
|
2019-07-16 16:10:44 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
# db_spin will query the database in a tight loop for the specified duration
|
|
|
|
def self.db_spin(duration_s, interval_s)
|
|
|
|
expected_end_time = Time.now + duration_s
|
|
|
|
|
|
|
|
while Time.now < expected_end_time
|
|
|
|
ActiveRecord::Base.connection.execute("SELECT 1")
|
|
|
|
|
|
|
|
end_interval_time = Time.now + [duration_s, interval_s].min
|
|
|
|
rand while Time.now < end_interval_time
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# sleep will sleep for the specified duration
|
|
|
|
def self.sleep(duration_s)
|
|
|
|
Kernel.sleep(duration_s)
|
|
|
|
end
|
|
|
|
|
2021-04-09 02:09:30 -04:00
|
|
|
# Kill will send the given signal to the current process.
|
|
|
|
def self.kill(signal)
|
|
|
|
Process.kill(signal, Process.pid)
|
2019-07-16 16:10:44 -04:00
|
|
|
end
|
2021-01-21 10:08:36 -05:00
|
|
|
|
|
|
|
def self.run_gc
|
|
|
|
# Tenure any live objects from young-gen to old-gen
|
|
|
|
4.times { GC.start(full_mark: false) }
|
|
|
|
# Run a full mark-and-sweep collection
|
|
|
|
GC.start
|
|
|
|
GC.stat
|
|
|
|
end
|
2019-07-16 16:10:44 -04:00
|
|
|
end
|
|
|
|
end
|