process-metrics 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/process/metrics/command/summary.rb +27 -25
- data/lib/process/metrics/general.rb +3 -1
- data/lib/process/metrics/memory/darwin.rb +50 -40
- data/lib/process/metrics/memory/linux.rb +17 -4
- data/lib/process/metrics/memory.rb +1 -1
- data/lib/process/metrics/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +1 -1
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbfff6ee5c7b2f09e1872bfaf86b520d999c94295de8d2328140ffeb84baa228
|
4
|
+
data.tar.gz: 2318ca3ac6a699863015b0f4ac32d22ee8845466f7046feee0155e89b9c5c5a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4a69c2cc8a4055fcb9cd3612459b4e1a1164b8a4ac4095dafc8e7b51126915c79673b6023bc09f87357d69ac0aaf71e0caae9c2d3dd6a4fd3a7f8482d368b00
|
7
|
+
data.tar.gz: 17363223b2c6858e5f2e0241267e6dbaf6e97f58631483ef95af6fd7ad349d59915a8e486a27011a259c64f290f4da8ced1ea96e47bb3d0eb193c877ffdf2591
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -44,6 +44,8 @@ module Process
|
|
44
44
|
options do
|
45
45
|
option "--pid <integer>", "Report on a single process id.", type: Integer, required: true
|
46
46
|
option "-p/--ppid <integer>", "Report on all children of this process id.", type: Integer, required: true
|
47
|
+
|
48
|
+
option "--total-memory <integer>", "Set the total memory relative to the usage (MiB).", type: Integer
|
47
49
|
end
|
48
50
|
|
49
51
|
def terminal
|
@@ -87,7 +89,7 @@ module Process
|
|
87
89
|
return "#{value.round(unit)}#{units[unit]}"
|
88
90
|
end
|
89
91
|
|
90
|
-
def
|
92
|
+
def format_memory(value, total, terminal)
|
91
93
|
if value > (total * 0.8)
|
92
94
|
intensity = :high
|
93
95
|
elsif value > (total * 0.5)
|
@@ -101,23 +103,23 @@ module Process
|
|
101
103
|
terminal.print(formatted, intensity, "[", Bar.format(value / total.to_f, 60), "]", :reset)
|
102
104
|
end
|
103
105
|
|
106
|
+
def total_memory
|
107
|
+
if total_memory = @options[:total_memory]
|
108
|
+
return total_memory * 1024
|
109
|
+
else
|
110
|
+
return Process::Metrics::Memory.total_size
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
104
114
|
def call
|
105
115
|
terminal = self.terminal
|
106
116
|
|
107
117
|
summary = Process::Metrics::General.capture(pid: @options[:pid], ppid: @options[:ppid])
|
108
118
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
summary.each do |pid, general|
|
115
|
-
if memory = general.memory
|
116
|
-
total_memory_usage += memory.proportional_size + memory.unique_size
|
117
|
-
else
|
118
|
-
total_memory_usage += general.resident_size
|
119
|
-
end
|
120
|
-
end
|
119
|
+
format_memory = self.method(:format_memory).curry
|
120
|
+
shared_memory = 0
|
121
|
+
private_memory = 0
|
122
|
+
total_memory = self.total_memory
|
121
123
|
|
122
124
|
proportional = true
|
123
125
|
|
@@ -129,25 +131,25 @@ module Process
|
|
129
131
|
terminal.print_line
|
130
132
|
|
131
133
|
if memory = general.memory
|
132
|
-
|
133
|
-
|
134
|
+
shared_memory += memory.proportional_size
|
135
|
+
private_memory += memory.unique_size
|
134
136
|
|
135
137
|
terminal.print_line(
|
136
|
-
:key, "
|
137
|
-
|
138
|
+
:key, "Memory: ".rjust(20), :reset,
|
139
|
+
format_memory[memory.proportional_size, total_memory]
|
138
140
|
)
|
139
141
|
|
140
142
|
terminal.print_line(
|
141
143
|
:key, "Private Memory: ".rjust(20), :reset,
|
142
|
-
|
144
|
+
format_memory[memory.unique_size, total_memory]
|
143
145
|
)
|
144
146
|
else
|
145
|
-
|
147
|
+
shared_memory += general.resident_size
|
146
148
|
proportional = false
|
147
149
|
|
148
150
|
terminal.print_line(
|
149
151
|
:key, "Memory: ".rjust(20), :reset,
|
150
|
-
|
152
|
+
format_memory[general.resident_size, total_memory]
|
151
153
|
)
|
152
154
|
end
|
153
155
|
end
|
@@ -156,24 +158,24 @@ module Process
|
|
156
158
|
|
157
159
|
if proportional
|
158
160
|
terminal.print_line(
|
159
|
-
:key, "
|
160
|
-
|
161
|
+
:key, "Memory: ".rjust(20), :reset,
|
162
|
+
format_memory[shared_memory, total_memory]
|
161
163
|
)
|
162
164
|
|
163
165
|
terminal.print_line(
|
164
166
|
:key, "Private Memory: ".rjust(20), :reset,
|
165
|
-
|
167
|
+
format_memory[private_memory, total_memory]
|
166
168
|
)
|
167
169
|
else
|
168
170
|
terminal.print_line(
|
169
171
|
:key, "Memory: ".rjust(20), :reset,
|
170
|
-
|
172
|
+
format_memory[memory, total_memory]
|
171
173
|
)
|
172
174
|
end
|
173
175
|
|
174
176
|
terminal.print_line(
|
175
177
|
:key, "Memory (Total): ".rjust(20), :reset,
|
176
|
-
|
178
|
+
format_memory[shared_memory + private_memory, total_memory]
|
177
179
|
)
|
178
180
|
end
|
179
181
|
end
|
@@ -113,8 +113,10 @@ module Process
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def self.capture_memory(processes)
|
116
|
+
count = processes.size
|
117
|
+
|
116
118
|
processes.each do |pid, process|
|
117
|
-
process.memory = Memory.capture(
|
119
|
+
process.memory = Memory.capture(pid, count: count)
|
118
120
|
end
|
119
121
|
end
|
120
122
|
|
@@ -13,6 +13,18 @@ module Process
|
|
13
13
|
File.executable?(VMMAP)
|
14
14
|
end
|
15
15
|
|
16
|
+
# @returns [Numeric] Total memory size in kilobytes.
|
17
|
+
def self.total_size
|
18
|
+
# sysctl hw.memsize
|
19
|
+
IO.popen(["sysctl", "hw.memsize"], "r") do |io|
|
20
|
+
io.each_line do |line|
|
21
|
+
if line =~ /hw.memsize: (\d+)/
|
22
|
+
return $1.to_i / 1024
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
16
28
|
# Parse a size string into kilobytes.
|
17
29
|
def self.parse_size(string)
|
18
30
|
return 0 unless string
|
@@ -35,51 +47,45 @@ module Process
|
|
35
47
|
/x
|
36
48
|
|
37
49
|
# Capture memory usage for the given process IDs.
|
38
|
-
def self.capture(
|
50
|
+
def self.capture(pid, count: 1, **options)
|
39
51
|
usage = Memory.zero
|
40
52
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# Anonymous memory: no region detail path or special names
|
70
|
-
if match[:region_name] =~ /MALLOC|VM_ALLOCATE|Stack|STACK|anonymous/
|
71
|
-
usage.anonymous_size += resident_size
|
72
|
-
end
|
73
|
-
# else
|
74
|
-
# puts "Failed to match line: #{line}"
|
53
|
+
IO.popen(["vmmap", pid.to_s], "r") do |io|
|
54
|
+
io.each_line do |line|
|
55
|
+
if match = LINE.match(line)
|
56
|
+
virtual_size = parse_size(match[:virtual_size])
|
57
|
+
resident_size = parse_size(match[:resident_size])
|
58
|
+
dirty_size = parse_size(match[:dirty_size])
|
59
|
+
swap_size = parse_size(match[:swap_size])
|
60
|
+
|
61
|
+
# Update counts
|
62
|
+
usage.map_count += 1
|
63
|
+
usage.resident_size += resident_size
|
64
|
+
usage.swap_size += swap_size
|
65
|
+
|
66
|
+
# Private vs. Shared memory
|
67
|
+
# COW=copy_on_write PRV=private NUL=empty ALI=aliased
|
68
|
+
# SHM=shared ZER=zero_filled S/A=shared_alias
|
69
|
+
case match[:sharing_mode]
|
70
|
+
when "PRV"
|
71
|
+
usage.private_clean_size += resident_size - dirty_size
|
72
|
+
usage.private_dirty_size += dirty_size
|
73
|
+
when "COW", "SHM"
|
74
|
+
usage.shared_clean_size += resident_size - dirty_size
|
75
|
+
usage.shared_dirty_size += dirty_size
|
76
|
+
end
|
77
|
+
|
78
|
+
# Anonymous memory: no region detail path or special names
|
79
|
+
if match[:region_name] =~ /MALLOC|VM_ALLOCATE|Stack|STACK|anonymous/
|
80
|
+
usage.anonymous_size += resident_size
|
75
81
|
end
|
76
82
|
end
|
77
83
|
end
|
78
84
|
end
|
79
85
|
|
80
|
-
#
|
81
|
-
usage.proportional_size = usage.resident_size
|
82
|
-
usage.proportional_swap_size = usage.swap_size
|
86
|
+
# Darwin does not expose proportional memory usage, so we guess based on the number of processes. Yes, this is a terrible hack, but it's the most reasonable thing to do given the constraints:
|
87
|
+
usage.proportional_size = usage.resident_size / count
|
88
|
+
usage.proportional_swap_size = usage.swap_size / count
|
83
89
|
|
84
90
|
return usage
|
85
91
|
end
|
@@ -91,8 +97,12 @@ module Process
|
|
91
97
|
return true
|
92
98
|
end
|
93
99
|
|
94
|
-
def
|
95
|
-
return Memory::Darwin.
|
100
|
+
def total_size
|
101
|
+
return Memory::Darwin.total_size
|
102
|
+
end
|
103
|
+
|
104
|
+
def capture(...)
|
105
|
+
return Memory::Darwin.capture(...)
|
96
106
|
end
|
97
107
|
end
|
98
108
|
end
|
@@ -6,6 +6,15 @@
|
|
6
6
|
module Process
|
7
7
|
module Metrics
|
8
8
|
class Memory::Linux
|
9
|
+
# @returns [Numeric] Total memory size in kilobytes.
|
10
|
+
def self.total_size
|
11
|
+
File.read("/proc/meminfo").each_line do |line|
|
12
|
+
if /MemTotal:\s+(?<total>\d+) kB/ =~ line
|
13
|
+
return total.to_i
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
9
18
|
# The fields that will be extracted from the `smaps` data.
|
10
19
|
SMAP = {
|
11
20
|
"Rss" => :resident_size,
|
@@ -53,10 +62,10 @@ module Process
|
|
53
62
|
end
|
54
63
|
|
55
64
|
# Capture memory usage for the given process IDs.
|
56
|
-
def self.capture(
|
65
|
+
def self.capture(pid, **options)
|
57
66
|
usage = Memory.zero
|
58
67
|
|
59
|
-
|
68
|
+
begin
|
60
69
|
File.foreach("/proc/#{pid}/smaps") do |line|
|
61
70
|
# The format of this is fixed according to:
|
62
71
|
# https://github.com/torvalds/linux/blob/351c8a09b00b5c51c8f58b016fffe51f87e2d820/fs/proc/task_mmu.c#L804-L814
|
@@ -89,8 +98,12 @@ module Process
|
|
89
98
|
return true
|
90
99
|
end
|
91
100
|
|
92
|
-
def
|
93
|
-
return Memory::Linux.
|
101
|
+
def total_size
|
102
|
+
return Memory::Linux.total_size
|
103
|
+
end
|
104
|
+
|
105
|
+
def capture(...)
|
106
|
+
return Memory::Linux.capture(...)
|
94
107
|
end
|
95
108
|
end
|
96
109
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
metadata.gz.sig
CHANGED
Binary file
|