diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 11:10:13 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-20 11:10:13 +0000 |
commit | 0ea3fcec397b69815975647f5e2aa5fe944a8486 (patch) | |
tree | 7979381b89d26011bcf9bdc989a40fcc2f1ed4ff /lib/gitlab/memory | |
parent | 72123183a20411a36d607d70b12d57c484394c8e (diff) | |
download | gitlab-ce-0ea3fcec397b69815975647f5e2aa5fe944a8486.tar.gz |
Add latest changes from gitlab-org/gitlab@15-1-stable-eev15.1.0-rc42
Diffstat (limited to 'lib/gitlab/memory')
-rw-r--r-- | lib/gitlab/memory/jemalloc.rb | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/lib/gitlab/memory/jemalloc.rb b/lib/gitlab/memory/jemalloc.rb new file mode 100644 index 00000000000..454c54569de --- /dev/null +++ b/lib/gitlab/memory/jemalloc.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true + +require 'fiddle' + +module Gitlab + module Memory + module Jemalloc + extend self + + STATS_FORMATS = { + json: { options: 'J', extension: 'json' }, + text: { options: '', extension: 'txt' } + }.freeze + + STATS_DEFAULT_FORMAT = :json + + # Return jemalloc stats as a string. + def stats(format: STATS_DEFAULT_FORMAT) + verify_format!(format) + + with_malloc_stats_print do |stats_print| + StringIO.new.tap { |io| write_stats(stats_print, io, STATS_FORMATS[format]) }.string + end + end + + # Write jemalloc stats to the given directory. + def dump_stats(path:, format: STATS_DEFAULT_FORMAT) + verify_format!(format) + + with_malloc_stats_print do |stats_print| + format_settings = STATS_FORMATS[format] + File.open(File.join(path, file_name(format_settings[:extension])), 'wb') do |io| + write_stats(stats_print, io, format_settings) + end + end + end + + private + + def verify_format!(format) + raise "format must be one of #{STATS_FORMATS.keys}" unless STATS_FORMATS.key?(format) + end + + def with_malloc_stats_print + fiddle_func = malloc_stats_print + return unless fiddle_func + + yield fiddle_func + end + + def malloc_stats_print + method = Fiddle::Handle.sym("malloc_stats_print") + + Fiddle::Function.new( + method, + # C signature: + # void (write_cb_t *write_cb, void *cbopaque, const char *opts) + # arg1: callback function pointer (see below) + # arg2: pointer to cbopaque holding additional callback data; always NULL here + # arg3: options string, affects output format (text or JSON) + # + # Callback signature (write_cb_t): + # void (void *, const char *) + # arg1: pointer to cbopaque data (see above; unused) + # arg2: pointer to string buffer holding textual output + [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], + Fiddle::TYPE_VOID + ) + rescue Fiddle::DLError + # This means the Fiddle::Handle to jemalloc was not open (jemalloc wasn't loaded) + # or already closed. Eiher way, return nil. + end + + def write_stats(stats_print, io, format) + callback = Fiddle::Closure::BlockCaller.new( + Fiddle::TYPE_VOID, [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP]) do |_, fragment| + io << fragment + end + + stats_print.call(callback, nil, format[:options]) + end + + def file_name(extension) + "jemalloc_stats.#{$$}.#{Time.current.to_i}.#{extension}" + end + end + end +end |