Skip to content

Commit fbb726e

Browse files
committed
MAINT: PR 839 revisions
* `log_get_derived_metrics()` was adjusted to inject all the records for a given module, because this is our initial target to replicate the stats in the old perl summary report * a new `log_get_bytes_bandwidth()` function was drafted in as a convenience wrapper to get MiB (total bytes) and bandwidth (MiB/s) values printed out in the old perl report * renamed the regression test for this PR and adjusted it to compare against the bytes/bandwidth strings present in the perl reports; so far, only a small subset of the STDIO results are working properly (see the xfails in this test..)
1 parent 30849ec commit fbb726e

File tree

2 files changed

+58
-34
lines changed

2 files changed

+58
-34
lines changed

darshan-util/pydarshan/darshan/backend/cffi_backend.py

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -676,9 +676,6 @@ def log_get_derived_metrics(log_path: str, mod_name: str):
676676
return None
677677
mod_type = _structdefs[mod_name]
678678

679-
buf = ffi.new("void **")
680-
r = libdutil.darshan_log_get_record(log_handle['handle'], modules[mod_name]['idx'], buf)
681-
rbuf = ffi.cast(mod_type, buf)
682679

683680
darshan_accumulator = ffi.new("darshan_accumulator *")
684681
print("before create")
@@ -697,14 +694,21 @@ def log_get_derived_metrics(log_path: str, mod_name: str):
697694
print("after create")
698695

699696
print("before inject")
700-
r = libdutil.darshan_accumulator_inject(darshan_accumulator[0], rbuf[0], 1)
701-
if r != 0:
702-
libdutil.darshan_free(buf[0])
703-
raise RuntimeError("A nonzero exit code was received from "
704-
"darshan_accumulator_inject() at the C level. "
705-
"It may be possible "
706-
"to retrieve additional information from the stderr "
707-
"stream.")
697+
buf = ffi.new("void **")
698+
r = 1
699+
while r >= 1:
700+
r = libdutil.darshan_log_get_record(log_handle['handle'], modules[mod_name]['idx'], buf)
701+
if r < 1:
702+
break
703+
rbuf = ffi.cast(mod_type, buf)
704+
r_i = libdutil.darshan_accumulator_inject(darshan_accumulator[0], rbuf[0], 1)
705+
if r_i != 0:
706+
libdutil.darshan_free(buf[0])
707+
raise RuntimeError("A nonzero exit code was received from "
708+
"darshan_accumulator_inject() at the C level. "
709+
"It may be possible "
710+
"to retrieve additional information from the stderr "
711+
"stream.")
708712
print("after inject")
709713
darshan_derived_metrics = ffi.new("struct darshan_derived_metrics *")
710714
print("before emit")
@@ -722,3 +726,20 @@ def log_get_derived_metrics(log_path: str, mod_name: str):
722726
#libdutil.darshan_accumulator_destroy(darshan_accumulator)
723727
libdutil.darshan_free(buf[0])
724728
return darshan_derived_metrics
729+
730+
731+
def log_get_bytes_bandwidth(log_path: str, mod_name: str) -> str:
732+
# get total bytes (in MiB) and bandwidth (in MiB/s) for
733+
# a given module -- this information was commonly reported
734+
# in the old perl-based summary reports
735+
darshan_derived_metrics = log_get_derived_metrics(log_path=log_path,
736+
mod_name=mod_name)
737+
total_mib = darshan_derived_metrics.total_bytes / 2 ** 20
738+
report = darshan.DarshanReport(log_path, read_all=True)
739+
fcounters_df = report.records[f"{mod_name}"].to_df()['fcounters']
740+
total_rw_time = (fcounters_df[f"{mod_name}_F_READ_TIME"].sum() +
741+
fcounters_df[f"{mod_name}_F_WRITE_TIME"].sum() +
742+
fcounters_df[f"{mod_name}_F_META_TIME"].sum())
743+
total_bw = total_mib / total_rw_time
744+
ret_str = f"I/O performance estimate (at the {mod_name} layer): transferred {total_mib:.1f} MiB at {total_bw:.2f} MiB/s"
745+
return ret_str

darshan-util/pydarshan/darshan/tests/test_cffi_misc.py

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -161,29 +161,32 @@ def test_log_get_generic_record(dtype):
161161
assert actual_fcounter_names == expected_fcounter_names
162162

163163

164-
@pytest.mark.parametrize("log_path", [
165-
"imbalanced-io.darshan",
164+
@pytest.mark.parametrize("log_path, mod_name, expected_str", [
165+
# the expected bytes/bandwidth strings are pasted
166+
# directly from the old perl summary reports
167+
("imbalanced-io.darshan",
168+
"STDIO",
169+
"I/O performance estimate (at the STDIO layer): transferred 1.1 MiB at 0.01 MiB/s"),
170+
("laytonjb_test1_id28730_6-7-43012-2131301613401632697_1.darshan",
171+
"STDIO",
172+
"I/O performance estimate (at the STDIO layer): transferred 0.0 MiB at 4.22 MiB/s"),
173+
pytest.param("runtime_and_dxt_heatmaps_diagonal_write_only.darshan",
174+
"POSIX",
175+
"I/O performance estimate (at the POSIX layer): transferred 0.0 MiB at 0.02 MiB/s",
176+
marks=pytest.mark.xfail(reason="Not sure why modules other than STDIO fail yet...")),
177+
pytest.param("treddy_mpi-io-test_id4373053_6-2-60198-9815401321915095332_1.darshan",
178+
"STDIO",
179+
"I/O performance estimate (at the STDIO layer): transferred 0.0 MiB at 16.47 MiB/s",
180+
marks=pytest.mark.xfail(reason="Something extra needed to account for MPI-IO?")),
166181
])
167-
def test_derived_metrics_basic(log_path):
182+
def test_derived_metrics_bytes_and_bandwidth(log_path, mod_name, expected_str):
168183
# test the basic scenario of retrieving
169-
# the derived metrics from all records for a given
170-
# module; the situation where you'd like to
171-
# retrieve derived metrics for a subset of records (i.e.,
172-
# a particular filename) is not tested here
184+
# the total data transferred and bandwidth
185+
# for all records in a given module; the situation
186+
# of accumulating drived metrics with filtering
187+
# (i.e., for a single filename) is not tested here
188+
173189
log_path = get_log_path(log_path)
174-
report = darshan.DarshanReport(log_path, read_all=True)
175-
for mod_name in report.modules:
176-
# if support is added for accumulator work on these
177-
# modules later on, the test will fail to raise an error,
178-
# causing the test to ultimately fail; that is good, it will
179-
# force us to acknowledge that the support was added intentionally
180-
# under the hood
181-
print("testing mod_name:", mod_name)
182-
if mod_name in {"LUSTRE"}:
183-
with pytest.raises(RuntimeError):
184-
derived_metrics = backend.log_get_derived_metrics(log_path=log_path,
185-
mod_name=mod_name)
186-
else:
187-
derived_metrics = backend.log_get_derived_metrics(log_path=log_path,
188-
mod_name=mod_name)
189-
# TODO: assert against values from i.e., perl reports
190+
actual_str = backend.log_get_bytes_bandwidth(log_path=log_path,
191+
mod_name=mod_name)
192+
assert actual_str == expected_str

0 commit comments

Comments
 (0)