From 01d858066a5d037d73b9dc52afa5e5a7971ca9cb Mon Sep 17 00:00:00 2001 From: Frederick Cheung Date: Sat, 6 Jul 2019 21:41:15 +0100 Subject: [PATCH 1/3] Implement faster version for Mac OS --- get_process_mem.gemspec | 1 + lib/get_process_mem.rb | 19 +++++++++++++ lib/get_process_mem/darwin.rb | 53 +++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 lib/get_process_mem/darwin.rb diff --git a/get_process_mem.gemspec b/get_process_mem.gemspec index a53c403..109e0b0 100644 --- a/get_process_mem.gemspec +++ b/get_process_mem.gemspec @@ -19,6 +19,7 @@ Gem::Specification.new do |gem| gem.require_paths = ["lib"] gem.add_development_dependency "sys-proctable", "~> 1.0" + gem.add_development_dependency "ffi", "~> 1.0" gem.add_development_dependency "rake", "~> 10.1" gem.add_development_dependency "test-unit", "~> 3.1.0" end diff --git a/lib/get_process_mem.rb b/lib/get_process_mem.rb index 4ef9cfe..ad352eb 100644 --- a/lib/get_process_mem.rb +++ b/lib/get_process_mem.rb @@ -31,6 +31,20 @@ class GetProcessMem include Sys end + RUNS_ON_DARWIN = Gem.platforms.detect do |p| + p.is_a?(Gem::Platform) && p.os == 'darwin' + end + + if RUNS_ON_DARWIN + begin + require 'get_process_mem/darwin' + rescue LoadError => e + message = "Please add `ffi` to your Gemfile for darwin (macos) machines\n" + message << e.message + raise e, message + end + end + def initialize(pid = Process.pid) @status_file = Pathname.new "/proc/#{pid}/status" @process_file = Pathname.new "/proc/#{pid}/smaps" @@ -44,6 +58,7 @@ def linux? def bytes memory = linux_status_memory if linux? + memory ||= darwin_memory if RUNS_ON_DARWIN memory ||= ps_memory end @@ -102,4 +117,8 @@ def ps_memory KB_TO_BYTE * number_to_bigdecimal(mem == "" ? 0 : mem) end end + + def darwin_memory + Darwin.resident_size + end end diff --git a/lib/get_process_mem/darwin.rb b/lib/get_process_mem/darwin.rb new file mode 100644 index 0000000..2fd98cb --- /dev/null +++ b/lib/get_process_mem/darwin.rb @@ -0,0 +1,53 @@ +require 'ffi' + +class GetProcessMem + class Darwin + extend FFI::Library + ffi_lib 'c' + attach_function :mach_task_self, [], :__darwin_mach_port_t + attach_function :task_info, + [ + :__darwin_mach_port_t, + :int, # return selector + :pointer, #pointer to task info + :pointer, #pointer to int (size of structure / bytes filled out) + ], + :int + + class IntPtr < FFI::Struct + layout :value, :int + end + + class TaskInfo < FFI::Struct + layout :suspend_count, :int32, + :virtual_size, :uint64, + :resident_size, :uint64, + :user_time, :uint64, + :system_time, :uint64, + :policy, :int32 + end + + MACH_TASK_BASIC_INFO = 20 + MACH_TASK_BASIC_INFO_COUNT = TaskInfo.size / FFI.type_size(:uint) + + class << self + def resident_size + mach_task_info[:resident_size] + end + + private + + def mach_task_info + data = TaskInfo.new + out_count = IntPtr.new + out_count[:value] = MACH_TASK_BASIC_INFO_COUNT + result = task_info(mach_task_self, MACH_TASK_BASIC_INFO, data, out_count) + if result == 0 + data + else + raise "task_info returned #{result}" + end + end + end + end +end From 35c35d81ac763dacf814bb7c691ff8fd4db590c3 Mon Sep 17 00:00:00 2001 From: schneems Date: Mon, 8 Jul 2019 10:55:00 -0500 Subject: [PATCH 2/3] Make FFI a default required gem https://github.com/schneems/get_process_mem/pull/32/files#diff-173a00b7e042c37f167da8b70dc62fe9R34 --- CHANGELOG.md | 8 ++++++-- get_process_mem.gemspec | 3 ++- lib/get_process_mem/version.rb | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33e2864..b372a37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ +## 0.2.4 + +- Use FFI to speed up memory lookup on Mac (darwin) by roughly 12x (#32) + ## 0.2.3 -- Silence BigDecimal deprecation warning under Ruby 2.5 (#26) +- Silence BigDecimal deprecation warning under Ruby 2.5 (#26) ## 0.2.2 @@ -25,4 +29,4 @@ ## 0.0.1 -- Initial \ No newline at end of file +- Initial diff --git a/get_process_mem.gemspec b/get_process_mem.gemspec index 109e0b0..b898eb7 100644 --- a/get_process_mem.gemspec +++ b/get_process_mem.gemspec @@ -18,8 +18,9 @@ Gem::Specification.new do |gem| gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) gem.require_paths = ["lib"] + gem.add_dependency "ffi", "~> 1.0" + gem.add_development_dependency "sys-proctable", "~> 1.0" - gem.add_development_dependency "ffi", "~> 1.0" gem.add_development_dependency "rake", "~> 10.1" gem.add_development_dependency "test-unit", "~> 3.1.0" end diff --git a/lib/get_process_mem/version.rb b/lib/get_process_mem/version.rb index e50e1e9..c42ff1b 100644 --- a/lib/get_process_mem/version.rb +++ b/lib/get_process_mem/version.rb @@ -1,3 +1,3 @@ class GetProcessMem - VERSION = "0.2.3" + VERSION = "0.2.4" end From c84afc6718c4ccc60f96701e657997cd612776a7 Mon Sep 17 00:00:00 2001 From: schneems Date: Mon, 8 Jul 2019 10:56:26 -0500 Subject: [PATCH 3/3] Test OSX specific changes on mac on travis --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2c9c8da..483ea23 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: ruby +os: + - linux + - osx before_install: - gem install bundler -v 1.12.5 @@ -14,4 +17,4 @@ matrix: allow_failures: - rvm: ruby-head - rvm: rbx-19mode - - rvm: jruby-19mode \ No newline at end of file + - rvm: jruby-19mode