# frozen_string_literal: true # This class uses a custom Ruby patch to allow # a per-thread memory allocation tracking in a efficient manner # # This concept is currently tried to be upstreamed here: # - https://github.com/ruby/ruby/pull/3978 module Gitlab module Memory class Instrumentation KEY_MAPPING = { total_allocated_objects: :mem_objects, total_malloc_bytes: :mem_bytes, total_mallocs: :mem_mallocs }.freeze MUTEX = Mutex.new def self.available? Thread.respond_to?(:trace_memory_allocations=) && Thread.current.respond_to?(:memory_allocations) end # This method changes a global state def self.ensure_feature_flag! return unless available? enabled = Feature.enabled?(:trace_memory_allocations, default_enabled: true) return if enabled == Thread.trace_memory_allocations MUTEX.synchronize do # This enables or disables feature dynamically # based on a feature flag Thread.trace_memory_allocations = enabled end end def self.start_thread_memory_allocations return unless available? ensure_feature_flag! # it will return `nil` if disabled Thread.current.memory_allocations end # This method returns a hash with the following keys: # - mem_objects: number of allocated heap slots (as reflected by GC) # - mem_mallocs: number of malloc calls # - mem_bytes: number of bytes allocated by malloc for objects that did not fit # into a heap slot # - mem_total_bytes: number of bytes allocated for both objects consuming an object slot # and objects that required a malloc (mem_malloc_bytes) def self.measure_thread_memory_allocations(previous) return unless available? return unless previous current = Thread.current.memory_allocations return unless current # calculate difference in a memory allocations result = previous.to_h do |key, value| [KEY_MAPPING.fetch(key), current[key].to_i - value] end result[:mem_total_bytes] = result[:mem_bytes] + result[:mem_objects] * GC::INTERNAL_CONSTANTS[:RVALUE_SIZE] result end def self.with_memory_allocations previous = self.start_thread_memory_allocations yield self.measure_thread_memory_allocations(previous) end end end end