8000 BUG: deallocate recursive closure in arrayprint.py by ahaldane · Pull Request #10621 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: deallocate recursive closure in arrayprint.py #10621

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 19, 2018
Merged
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
19 changes: 12 additions & 7 deletions numpy/core/arrayprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,8 @@ def recurser(index, hanging_indent, curr_width):
s += hanging_indent + summary_insert + line_sep

for i in range(trailing_items, 1, -1):
nested = recurser(index + (-i,), next_hanging_indent, next_width)
nested = recurser(index + (-i,), next_hanging_indent,
next_width)
s += hanging_indent + nested + line_sep

nested = recurser(index + (-1,), next_hanging_indent, next_width)
Expand All @@ -782,12 +783,16 @@ def recurser(index, hanging_indent, curr_width):
s = '[' + s[len(hanging_indent):] + ']'
return s

# invoke the recursive part with an initial index and prefix
return recurser(
index=(),
hanging_indent=next_line_prefix,
curr_width=line_width)

try:
# invoke the recursive part with an initial index and prefix
return recurser(index=(),
hanging_indent=next_line_prefix,
curr_width=line_width)
finally:
# recursive closures have a cyclic reference to themselves, which
# requires gc to collect (gh-10620). To avoid this problem, for
# performance and PyPy friendliness, we break the cycle:
Copy link
Member

Choose a reason for hiding this comment

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

Also to avoid UPDATE_IF_COPY interactions, but no need to mention that here

recurser = None

def _none_or_positive_arg(x, name):
if x is None:
Expand Down
8 changes: 7 additions & 1 deletion numpy/core/shape_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,13 @@ def block_recursion(arrays, depth=0):
# type(arrays) is not list
return atleast_nd(arrays, result_ndim)

return block_recursion(arrays)
try:
return block_recursion(arrays)
finally:
# recursive closures have a cyclic reference to themselves, which
# requires gc to collect (gh-10620). To avoid this problem, for
# performance and PyPy friendliness, we break the cycle:
block_recursion = None


def block(arrays):
Expand Down
14 changes: 13 additions & 1 deletion numpy/core/tests/test_arrayprint.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import division, absolute_import, print_function

import sys
import sys, gc

import numpy as np
from numpy.testing import (
Expand Down Expand Up @@ -355,6 +355,18 @@ def test_wide_element(self):
"[ 'xxxxx']"
)

def test_refcount(self):
# make sure we do not hold references to the array due to a recursive
# closure (gh-10620)
gc.disable()
a = np.arange(2)
r1 = sys.getrefcount(a)
np.array2string(a)
np.array2string(a)
r2 = sys.getrefcount(a)
gc.collect()
gc.enable()
assert_(r1 == r2)

class TestPrintOptions(object):
"""Test getting and setting global print options."""
Expand Down
5 changes: 5 additions & 0 deletions numpy/lib/npyio.py
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,11 @@ def tobytes_first(x, conv):
finally:
if fown:
fh.close()
# recursive closures have a cyclic reference to themselves, which
# requires gc to collect (gh-10620). To avoid this problem, for
# performance and PyPy friendliness, we break the cycle:
flatten_dtype_internal = None
pack_items = None

if X is None:
X = np.array([], dtype)
Expand Down
0