Skip to content

Commit a23ddbe

Browse files
ahmadelyousseffacebook-github-bot
authored andcommitted
Adding numastat and ulimit to system specs (#200)
Summary: Pull Request resolved: #200 Adding numastat -m and ulimit -a outputs to system_specs results. Reviewed By: excelle08 Differential Revision: D80288881 fbshipit-source-id: 78afe2dc37cd9c4e088aff2856202f3e7903870e
1 parent 022ec0b commit a23ddbe

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

benchpress/cli/commands/run.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ def run(self, args, jobs) -> None:
129129
os_release_data = sys_specs.get_os_release_data()
130130
kernel_cmdline = sys_specs.get_kernel_cmdline()
131131
dmidecode_data = sys_specs.get_dmidecode_data()
132+
numastat_data = sys_specs.get_numastat()
133+
ulimit_data = sys_specs.get_ulimit()
132134
sys_packages = []
133135
if "id" in os_release_data:
134136
os_id = os_release_data["id"].lower()
@@ -152,6 +154,8 @@ def run(self, args, jobs) -> None:
152154
sys_specs_dict["memory"] = mem_data
153155
sys_specs_dict["hardware"] = hw_data
154156
sys_specs_dict["os-release"] = os_release_data
157+
sys_specs_dict["numastat"] = numastat_data
158+
sys_specs_dict["ulimit"] = ulimit_data
155159

156160
final_metrics = {}
157161
if "machines" not in final_metrics:

benchpress/lib/sys_specs.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,126 @@ def get_os_release_data():
158158
os_release_data_dict[param] = param_val
159159

160160
return os_release_data_dict
161+
162+
163+
def get_numastat():
164+
numastat_p = subprocess.Popen(
165+
["numastat", "-m"], stdout=subprocess.PIPE, stderr=subprocess.PIPE
166+
)
167+
(numastat_data, err) = numastat_p.communicate()
168+
numastat_data = numastat_data.decode("utf-8").split("\n")
169+
170+
numastat_dict = {}
171+
headers = []
172+
found_headers = False
173+
174+
for line in numastat_data:
175+
line = line.strip()
176+
if not line:
177+
continue
178+
179+
# Skip the first line (title line)
180+
if "Per-node system memory usage" in line:
181+
continue
182+
183+
# Look for the header line with Node names and Total
184+
if not found_headers and ("Node" in line or "Total" in line):
185+
# Parse headers by combining "Node" with following numbers
186+
parts = line.split()
187+
headers = []
188+
i = 0
189+
while i < len(parts):
190+
if parts[i] == "Node" and i + 1 < len(parts) and parts[i + 1].isdigit():
191+
headers.append(f"Node {parts[i + 1]}")
192+
i += 2
193+
elif parts[i] == "Total":
194+
headers.append("Total")
195+
i += 1
196+
else:
197+
i += 1
198+
199+
# Initialize dictionaries for each node/total
200+
for header in headers:
201+
numastat_dict[header] = {}
202+
found_headers = True
203+
continue
204+
205+
# Skip separator lines (lines with dashes)
206+
if found_headers and "-" in line:
207+
continue
208+
209+
# Parse data lines
210+
if found_headers:
211+
parts = line.split()
212+
if len(parts) >= 2:
213+
metric_name = parts[0]
214+
values = parts[1:]
215+
216+
# Assign values to each node/total
217+
for i, value in enumerate(values):
218+
if i < len(headers): # Make sure we don't go out of bounds
219+
header = headers[i]
220+
try:
221+
numastat_dict[header][metric_name] = float(value)
222+
except ValueError:
223+
# If conversion to float fails, store as string
224+
numastat_dict[header][metric_name] = value
225+
226+
return numastat_dict
227+
228+
229+
def get_ulimit():
230+
ulimit_p = subprocess.Popen(
231+
"ulimit -a", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
232+
)
233+
(ulimit_data, err) = ulimit_p.communicate()
234+
ulimit_data = ulimit_data.decode("utf-8").split("\n")
235+
236+
ulimit_dict = {}
237+
238+
for line in ulimit_data:
239+
line = line.strip()
240+
if not line:
241+
continue
242+
243+
# Find the last occurrence of parentheses which contains the flag
244+
last_paren_start = line.rfind("(")
245+
last_paren_end = line.rfind(")")
246+
247+
if last_paren_start == -1 or last_paren_end == -1:
248+
continue
249+
250+
# Extract the description (everything before the last parentheses)
251+
description_part = line[:last_paren_start].strip()
252+
253+
# Extract the flag and unit (inside the last parentheses)
254+
flag_part = line[last_paren_start + 1 : last_paren_end]
255+
# The flag is typically the last part after comma and space
256+
if ", " in flag_part:
257+
unit_part = flag_part.split(", ")[0] # Everything before the comma
258+
flag = flag_part.split(", ")[-1] # Everything after the comma
259+
description = f"{description_part} ({unit_part})"
260+
else:
261+
flag = flag_part
262+
description = description_part
263+
264+
# Extract the value (everything after the last parentheses)
265+
value_str = line[last_paren_end + 1 :].strip()
266+
267+
# Try to convert value to appropriate type
268+
if value_str == "unlimited":
269+
value = "unlimited"
270+
else:
271+
try:
272+
# Try integer first
273+
if "." not in value_str:
274+
value = int(value_str)
275+
else:
276+
value = float(value_str)
277+
except ValueError:
278+
# If conversion fails, keep as string
279+
value = value_str
280+
281+
ulimit_dict[description] = {"flag": flag, "value": value}
282+
283+
return ulimit_dict

0 commit comments

Comments
 (0)