diff options
author | Igor Ganichev <iga@google.com> | 2018-09-12 13:32:04 -0700 |
---|---|---|
committer | TensorFlower Gardener <gardener@tensorflow.org> | 2018-09-12 13:37:15 -0700 |
commit | 52d9dbfa8ed7bc8b91f1a1be706cf77314b1c687 (patch) | |
tree | 54c82f0460f003f6f5ba75a9ab081017909cf1da /tensorflow/python/util | |
parent | 5d1de24583aabeb2cb883ab197ae2b8d5446c565 (diff) |
Use WeakKeyDictionaries for global Keras {graph->...} maps
These globals were holding onto graphs including FuncGraphs, which
held onto captured tensors leaving garbage around.
This change also adds a test to catch garbage like this in the future.
To make the test work, I needed to manually breakup some reference
cycles caused by OrderedDicts. We should probably have a custom impl
of OrderedDict similar to the one in Python3 and avoid these issues.
PiperOrigin-RevId: 212694290
Diffstat (limited to 'tensorflow/python/util')
-rw-r--r-- | tensorflow/python/util/memory.py | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/tensorflow/python/util/memory.py b/tensorflow/python/util/memory.py new file mode 100644 index 0000000000..e78f6d509a --- /dev/null +++ b/tensorflow/python/util/memory.py @@ -0,0 +1,45 @@ +# Copyright 2018 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== + +"""Functions related to Python memory management.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + + +# TODO(b/115366440): Delete this function when a custom OrderedDict is added +def dismantle_ordered_dict(ordered_dict): + """Remove reference cycle in OrderedDict `ordered_dict`. + + Helpful for making sure the garbage collector doesn't need to run after + using an OrderedDict. + + Args: + ordered_dict: A `OrderedDict` object to destroy. This object is unusable + after this function runs. + """ + # OrderedDict, makes a simple reference loop + # and hides it in an __attribute in some Python versions. We don't need to + # throw an error if we can't find it, but if we do find it we can break the + # loop to avoid creating work for the garbage collector. + problematic_cycle = ordered_dict.__dict__.get("_OrderedDict__root", None) # pylint: disable=protected-access + if problematic_cycle: + try: + del problematic_cycle[0][:] + except TypeError: + # This is probably not one of the problematic Python versions. Continue + # with the rest of our cleanup. + pass |