diff options
author | 2018-05-09 09:42:18 -0700 | |
---|---|---|
committer | 2018-05-09 10:52:05 -0700 | |
commit | 16986a1c9ed64c2312ededf733f20a137b521819 (patch) | |
tree | 1b3f281941851a8c51cfe77a82df4fc574dfff88 /tensorflow/core/common_runtime/function_threadpool_test.cc | |
parent | bcec296af809947145a6ebfa1e46b1cafe21ec06 (diff) |
[Functions] Fix unbounded memory growth in FunctionLibraryRuntime.
A recent change modified the behavior of `FunctionLibraryRuntimeImpl::ReleaseHandle()`
so that it no longer freed the memory associated with an instantiated function. Since
we rely on instantiating and releasing a potentially large number of instances of the
same function in tf.data to isolate the (e.g. random number generator) state in each
instance, this change meant that the memory consumption could grow without bound in
a simple program like:
```python
ds = tf.data.Dataset.from_tensors(0).repeat(None)
# The function `lambda y: y + 1` would be instantiated for each element in the input.
ds = ds.flat_map(lambda x: tf.data.Dataset.from_tensors(x).map(
lambda y: y + tf.random_uniform([], minval=0, maxval=10, dtype=tf.int32)))
iterator = ds.make_one_shot_iterator()
next_elem = iterator.get_next()
with tf.Session() as sess:
while True:
sess.run(next_elem)
```
PiperOrigin-RevId: 195983977
Diffstat (limited to 'tensorflow/core/common_runtime/function_threadpool_test.cc')
-rw-r--r-- | tensorflow/core/common_runtime/function_threadpool_test.cc | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/tensorflow/core/common_runtime/function_threadpool_test.cc b/tensorflow/core/common_runtime/function_threadpool_test.cc index 98dac38a8c..2d09e83d01 100644 --- a/tensorflow/core/common_runtime/function_threadpool_test.cc +++ b/tensorflow/core/common_runtime/function_threadpool_test.cc @@ -144,7 +144,19 @@ class FunctionLibraryRuntimeTest : public ::testing::Test { return status; } FunctionLibraryRuntime::Options opts; - return Run(flr, handle, opts, args, std::move(rets), add_runner); + status = Run(flr, handle, opts, args, rets, add_runner); + if (!status.ok()) return status; + + // Release the handle and try running again. It should not succeed. + status = flr->ReleaseHandle(handle); + if (!status.ok()) return status; + + Status status2 = Run(flr, handle, opts, args, std::move(rets)); + EXPECT_TRUE(errors::IsInvalidArgument(status2)); + EXPECT_TRUE( + str_util::StrContains(status2.error_message(), "remote execution.")); + + return status; } Status Run(FunctionLibraryRuntime* flr, FunctionLibraryRuntime::Handle handle, |