Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package/AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ Chronological list of authors
- Sai Udayagiri
- Apoorva Verma
- Aryaman Chaudhri
- Erik Fransson

External code
-------------
Expand Down
7 changes: 6 additions & 1 deletion package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ The rules for this file:
spyke7, talagayev, tanii1125, BradyAJohnston, hejamu, jeremyleung521,
harshitgajjela-droid, kunjsinha, aygarwal, jauy123, Dreamstick9,
ollyfutur, Amarendra22, charity-g, ParthUppal523, apoorva-01, RMeli,
raulloiscuns, Aryaman-Chaudhri
raulloiscuns, Aryaman-Chaudhri, erikfransson

* 2.11.0

Fixes
* The NCDF reader now releases the pages of the memory map once a frame has
been read into the Timestep. Reading a netCDF trajectory with `mmap=True`
(the default for a file name) no longer grows the resident memory of the
process towards the size of the whole trajectory file. Requires a platform
that provides `MADV_DONTNEED`, i.e. not Windows (Discussion #4792).
* Added `.gitattributes` to enforce LF (\n) as line endings and renormalized
existing files to conform (Issue #5315, PR #5446)
* `AtomGroup.rotate()` and the `rotateby` trajectory transformation now
Expand Down
10 changes: 10 additions & 0 deletions package/MDAnalysis/coordinates/TRJ.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
import warnings
import errno
import logging
import mmap
from math import isclose

import MDAnalysis
Expand Down Expand Up @@ -422,6 +423,11 @@ class NCDFReader(base.ReaderBase):
the first two frames of the trajectory.
:meth:`Writer` now also sets `convert_units`, `velocities`, `forces` and
`scale_factor` information for the :class:`NCDFWriter`.
.. versionchanged:: 2.11.0
The pages of the memory map are released after every frame, so that
memory use no longer grows towards the size of the trajectory file
while it is read. Requires ``MADV_DONTNEED``, which is not available
on Windows.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I don't think it is necessary to add a versionchanged directive for a bug fix--mostly just appropriate for user-facing behavior changes, otherwise we may have way too many such directives.


"""

Expand Down Expand Up @@ -675,6 +681,10 @@ def _read_frame(self, frame):
self.convert_pos_from_native(ts.dimensions[:3])
ts.frame = frame # frame labels are 0-based
self._current_frame = frame
# the frame is now copied into ts, so its pages can be dropped again
mm = getattr(self.trjfile, "_mm", None)
if mm is not None and hasattr(mmap, "MADV_DONTNEED"):
mm.madvise(mmap.MADV_DONTNEED)
return ts

def _reopen(self):
Expand Down
18 changes: 18 additions & 0 deletions testsuite/MDAnalysisTests/coordinates/test_netcdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
#
import MDAnalysis as mda
import numpy as np
import mmap
import sys

from scipy.io import netcdf_file
from types import SimpleNamespace

import pytest
from numpy.testing import assert_equal, assert_almost_equal
Expand Down Expand Up @@ -148,6 +150,22 @@ class TestNCDFReaderTZ2(_NCDFReaderTest, RefTZ2):
pass


@pytest.mark.skipif(
not hasattr(mmap, "MADV_DONTNEED"), reason="no MADV_DONTNEED"
)
def test_mmap_pages_dropped(monkeypatch):
"""Reading a frame releases its pages of the memory map."""
universe = mda.Universe(PRM_NCBOX, TRJ_NCBOX, mmap=True)
advice = []
monkeypatch.setattr(
universe.trajectory.trjfile,
"_mm",
SimpleNamespace(madvise=advice.append),
)
universe.trajectory[1]
assert advice == [mmap.MADV_DONTNEED]

@tylerjereddy tylerjereddy Aug 31, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test is a bit convoluted with monkeypatch--could we avoid that?

Also, am I understanding correctly that on this branch something like https://github.com/pythonprofilers/memory_profiler should show a constant level of physical memory consumption, while it should increase linearly when reading in/iterating over a trajecotry of the appropriate type on the develop branch?

We could probably capture that with https://asv.readthedocs.io/en/stable/writing_benchmarks.html#peak-memory as well, assuming you're saying that physical memory is being used excessively on develop in these scenarios.



class TestNCDFReader2(object):
"""NCDF Trajectory with positions and forces.

Expand Down
Loading