coveralls: 
[![Coverage Status](https://coveralls.io/builds/24779343/badge)](https://coveralls.io/builds/24779343)

Coverage decreased (-1.4%) to 98.226% when pulling **147d2dc7030437439532855450eee2faab793bab on dargueta:memoryfs-close** into **37b46b4a991a124f4d8e199e111ee21f00c2213b on PyFilesystem:master**.

dargueta: I know the contributors list is supposed to be sorted alphabetically but do I *really* need to put my name at the top? Feels weird.
willmcgugan: @dargueta It's cool. The idea was that the order doesn't indicate significance of contribution.

PR looks good BTW, thanks. I'll give it another review soon.
willmcgugan: Thanks
diff --git a/CHANGELOG.md b/CHANGELOG.md
index aaf125a..b36f9a9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](http://keepachangelog.com/)
 and this project adheres to [Semantic Versioning](http://semver.org/).
 
+## [2.4.9] - (Unreleased)
+
+### Changed
+
+- `MemFS` now immediately releases all memory it holds when `close()` is called,
+  rather than when it gets garbage collected. Closes [issue #308](https://github.com/PyFilesystem/pyfilesystem2/issues/308).
+
 ## [2.4.8] - 2019-06-12
 
 ### Changed
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 5c2a9b5..ef1d3a0 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -2,6 +2,7 @@
 
 Many thanks to the following developers for contributing to this project:
 
+- [Diego Argueta](https://github.com/dargueta)
 - [Geoff Jukes](https://github.com/geoffjukes)
 - [Giampaolo](https://github.com/gpcimino)
 - [Martin Larralde](https://github.com/althonos)
diff --git a/fs/memoryfs.py b/fs/memoryfs.py
index 2446b0d..dcee49d 100644
--- a/fs/memoryfs.py
+++ b/fs/memoryfs.py
@@ -340,6 +340,11 @@ class MemoryFS(FS):
                 current_entry = current_entry.get_entry(path_component)
             return current_entry
 
+    def close(self):
+        # type: () -> None
+        self.root = None
+        return super(MemoryFS, self).close()
+
     def getinfo(self, path, namespaces=None):
         # type: (Text, Optional[Collection[Text]]) -> Info
         namespaces = namespaces or ()

Free memory on MemoryFS.close
Steps to reproduce:

1. Run this piece of code in your favorite REPL.
```python
from fs.memoryfs import MemoryFS

mem_fs = MemoryFS()
with open('large_binary_file', 'rb') as f:
	mem_fs.upload('/large_binary_file', f)
mem_fs.close()
```
2. Watch python process before and after running this script.
3. The memory is there and the files are not removed.
4. Run `del mem_fs` and it immediately claims back the memory.
diff --git a/tests/test_memoryfs.py b/tests/test_memoryfs.py
index 8f8adbd..aaf6e77 100644
--- a/tests/test_memoryfs.py
+++ b/tests/test_memoryfs.py
@@ -1,9 +1,17 @@
 from __future__ import unicode_literals
 
+import posixpath
 import unittest
 
 from fs import memoryfs
 from fs.test import FSTestCases
+from fs.test import UNICODE_TEXT
+
+try:
+    # Only supported on Python 3.4+
+    import tracemalloc
+except ImportError:
+    tracemalloc = None
 
 
 class TestMemoryFS(FSTestCases, unittest.TestCase):
@@ -11,3 +19,50 @@ class TestMemoryFS(FSTestCases, unittest.TestCase):
 
     def make_fs(self):
         return memoryfs.MemoryFS()
+
+    def _create_many_files(self):
+        for parent_dir in {"/", "/one", "/one/two", "/one/other-two/three"}:
+            self.fs.makedirs(parent_dir, recreate=True)
+            for file_id in range(50):
+                self.fs.writetext(
+                    posixpath.join(parent_dir, str(file_id)), UNICODE_TEXT
+                )
+
+    @unittest.skipIf(
+        not tracemalloc, "`tracemalloc` isn't supported on this Python version."
+    )
+    def test_close_mem_free(self):
+        """Ensure all file memory is freed when calling close().
+
+        Prevents regression against issue #308.
+        """
+        trace_filters = [tracemalloc.Filter(True, "*/memoryfs.py")]
+        tracemalloc.start()
+
+        before = tracemalloc.take_snapshot().filter_traces(trace_filters)
+        self._create_many_files()
+        after_create = tracemalloc.take_snapshot().filter_traces(trace_filters)
+
+        self.fs.close()
+        after_close = tracemalloc.take_snapshot().filter_traces(trace_filters)
+        tracemalloc.stop()
+
+        [diff_create] = after_create.compare_to(
+            before, key_type="filename", cumulative=True
+        )
+        self.assertGreater(
+            diff_create.size_diff,
+            0,
+            "Memory usage didn't increase after creating files; diff is %0.2f KiB."
+            % (diff_create.size_diff / 1024.0),
+        )
+
+        [diff_close] = after_close.compare_to(
+            after_create, key_type="filename", cumulative=True
+        )
+        self.assertLess(
+            diff_close.size_diff,
+            0,
+            "Memory usage increased after closing the file system; diff is %0.2f KiB."
+            % (diff_close.size_diff / 1024.0),
+        )

pip install -e .[dev]
parse_log_pytest
requirements.txt
coverage mock pyftpdlib python-coveralls nose pytest
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
appdirs==1.4.4
attrs==22.2.0
certifi==2021.5.30
charset-normalizer==2.0.12
coverage==6.2
-e git+https://github.com/PyFilesystem/pyfilesystem2.git@37b46b4a991a124f4d8e199e111ee21f00c2213b#egg=fs
idna==3.10
importlib-metadata==4.8.3
iniconfig==1.1.1
mock==5.2.0
nose==1.3.7
packaging==21.3
pluggy==1.0.0
py==1.11.0
pyftpdlib==2.0.1
pyparsing==3.1.4
pytest==7.0.1
python-coveralls==2.9.3
pytz==2025.2
PyYAML==6.0.1
requests==2.27.1
six==1.10.0
tomli==1.2.3
typing_extensions==4.1.1
urllib3==1.26.20
zipp==3.6.0

name: pyfilesystem2
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - appdirs==1.4.4
      - attrs==22.2.0
      - charset-normalizer==2.0.12
      - coverage==6.2
      - idna==3.10
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - mock==5.2.0
      - nose==1.3.7
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyftpdlib==2.0.1
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-coveralls==2.9.3
      - pytz==2025.2
      - pyyaml==6.0.1
      - requests==2.27.1
      - six==1.10.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - zipp==3.6.0
prefix: /opt/conda/envs/pyfilesystem2

tests/test_memoryfs.py::TestMemoryFS::test_close_mem_free
tests/test_memoryfs.py::TestMemoryFS::test_appendbytes tests/test_memoryfs.py::TestMemoryFS::test_appendtext tests/test_memoryfs.py::TestMemoryFS::test_basic tests/test_memoryfs.py::TestMemoryFS::test_bin_files tests/test_memoryfs.py::TestMemoryFS::test_case_sensitive tests/test_memoryfs.py::TestMemoryFS::test_close tests/test_memoryfs.py::TestMemoryFS::test_copy tests/test_memoryfs.py::TestMemoryFS::test_copy_dir_mem tests/test_memoryfs.py::TestMemoryFS::test_copy_dir_temp tests/test_memoryfs.py::TestMemoryFS::test_copy_file tests/test_memoryfs.py::TestMemoryFS::test_copy_structure tests/test_memoryfs.py::TestMemoryFS::test_copydir tests/test_memoryfs.py::TestMemoryFS::test_create tests/test_memoryfs.py::TestMemoryFS::test_desc tests/test_memoryfs.py::TestMemoryFS::test_download tests/test_memoryfs.py::TestMemoryFS::test_download_0 tests/test_memoryfs.py::TestMemoryFS::test_download_1 tests/test_memoryfs.py::TestMemoryFS::test_download_2 tests/test_memoryfs.py::TestMemoryFS::test_download_4 tests/test_memoryfs.py::TestMemoryFS::test_download_chunk_size tests/test_memoryfs.py::TestMemoryFS::test_exists tests/test_memoryfs.py::TestMemoryFS::test_files tests/test_memoryfs.py::TestMemoryFS::test_filterdir tests/test_memoryfs.py::TestMemoryFS::test_getinfo tests/test_memoryfs.py::TestMemoryFS::test_getmeta tests/test_memoryfs.py::TestMemoryFS::test_getsize tests/test_memoryfs.py::TestMemoryFS::test_getsyspath tests/test_memoryfs.py::TestMemoryFS::test_geturl tests/test_memoryfs.py::TestMemoryFS::test_geturl_purpose tests/test_memoryfs.py::TestMemoryFS::test_glob tests/test_memoryfs.py::TestMemoryFS::test_hash tests/test_memoryfs.py::TestMemoryFS::test_invalid_chars tests/test_memoryfs.py::TestMemoryFS::test_isdir tests/test_memoryfs.py::TestMemoryFS::test_isempty tests/test_memoryfs.py::TestMemoryFS::test_isfile tests/test_memoryfs.py::TestMemoryFS::test_islink tests/test_memoryfs.py::TestMemoryFS::test_listdir tests/test_memoryfs.py::TestMemoryFS::test_makedir tests/test_memoryfs.py::TestMemoryFS::test_makedirs tests/test_memoryfs.py::TestMemoryFS::test_match tests/test_memoryfs.py::TestMemoryFS::test_move tests/test_memoryfs.py::TestMemoryFS::test_move_dir_mem tests/test_memoryfs.py::TestMemoryFS::test_move_dir_temp tests/test_memoryfs.py::TestMemoryFS::test_move_file_mem tests/test_memoryfs.py::TestMemoryFS::test_move_file_same_fs tests/test_memoryfs.py::TestMemoryFS::test_move_file_temp tests/test_memoryfs.py::TestMemoryFS::test_move_same_fs tests/test_memoryfs.py::TestMemoryFS::test_movedir tests/test_memoryfs.py::TestMemoryFS::test_open tests/test_memoryfs.py::TestMemoryFS::test_open_exclusive tests/test_memoryfs.py::TestMemoryFS::test_open_files tests/test_memoryfs.py::TestMemoryFS::test_openbin tests/test_memoryfs.py::TestMemoryFS::test_openbin_exclusive tests/test_memoryfs.py::TestMemoryFS::test_openbin_rw tests/test_memoryfs.py::TestMemoryFS::test_opendir tests/test_memoryfs.py::TestMemoryFS::test_readbytes tests/test_memoryfs.py::TestMemoryFS::test_readtext tests/test_memoryfs.py::TestMemoryFS::test_remove tests/test_memoryfs.py::TestMemoryFS::test_removedir tests/test_memoryfs.py::TestMemoryFS::test_removetree tests/test_memoryfs.py::TestMemoryFS::test_repeat_dir tests/test_memoryfs.py::TestMemoryFS::test_root_dir tests/test_memoryfs.py::TestMemoryFS::test_scandir tests/test_memoryfs.py::TestMemoryFS::test_setinfo tests/test_memoryfs.py::TestMemoryFS::test_settimes tests/test_memoryfs.py::TestMemoryFS::test_touch tests/test_memoryfs.py::TestMemoryFS::test_tree tests/test_memoryfs.py::TestMemoryFS::test_unicode_path tests/test_memoryfs.py::TestMemoryFS::test_upload tests/test_memoryfs.py::TestMemoryFS::test_upload_0 tests/test_memoryfs.py::TestMemoryFS::test_upload_1 tests/test_memoryfs.py::TestMemoryFS::test_upload_2 tests/test_memoryfs.py::TestMemoryFS::test_upload_4 tests/test_memoryfs.py::TestMemoryFS::test_upload_chunk_size tests/test_memoryfs.py::TestMemoryFS::test_validatepath tests/test_memoryfs.py::TestMemoryFS::test_writebytes tests/test_memoryfs.py::TestMemoryFS::test_writefile tests/test_memoryfs.py::TestMemoryFS::test_writetext
CONTRIBUTORS.md fs/memoryfs.py CHANGELOG.md
CONTRIBUTORS.md fs/memoryfs.py CHANGELOG.md