python / cpython

The Python programming language
https://www.python.org
Other
62.47k stars 29.99k forks source link

Does json.dumps have a memory leak? #76226

Closed 5676d9fc-c7c7-45d2-a8dc-1cf3ef0ca594 closed 6 years ago

5676d9fc-c7c7-45d2-a8dc-1cf3ef0ca594 commented 6 years ago
BPO 32045
Nosy @pitrou, @serhiy-storchaka, @csabella

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields: ```python assignee = None closed_at = created_at = labels = ['invalid', 'library'] title = 'Does json.dumps have a memory leak?' updated_at = user = 'https://bugs.python.org/rohandsa' ``` bugs.python.org fields: ```python activity = actor = 'cheryl.sabella' assignee = 'none' closed = True closed_date = closer = 'cheryl.sabella' components = ['Library (Lib)'] creation = creator = 'rohandsa' dependencies = [] files = [] hgrepos = [] issue_num = 32045 keywords = [] message_count = 5.0 messages = ['306344', '306345', '306414', '311290', '311291'] nosy_count = 4.0 nosy_names = ['pitrou', 'serhiy.storchaka', 'cheryl.sabella', 'rohandsa'] pr_nums = [] priority = 'normal' resolution = 'not a bug' stage = 'resolved' status = 'closed' superseder = None type = None url = 'https://bugs.python.org/issue32045' versions = ['Python 3.6'] ```

5676d9fc-c7c7-45d2-a8dc-1cf3ef0ca594 commented 6 years ago
import gc, json

class leak(object):
    def __init__(self):
        pass

gc.set_debug(gc.DEBUG_LEAK)
while True:
    leak_ = leak()
    json.dumps(leak_.__dict__, indent=True)
    gc.collect()
    print(f"garbage count: {len(gc.garbage)}")

Using the following code under Python 3.6.3, the garbage count keeps increasing and windows task manager records steady memory increase.

However without indent json.dumps(self.__dict__), no leak is observed.

serhiy-storchaka commented 6 years ago
indent=True just makes json to use Python implementation instead of C implementation. Python implementation uses closures which reference one other. Simple example not involving json is:

import gc

def f():
    def g():
        return h
    def h():
        return g
    return

gc.set_debug(gc.DEBUG_LEAK)
while True:
    f()
    gc.collect()
    print(f"garbage count: {len(gc.garbage)}")

The "leak" is caused by using gc.set_debug(gc.DEBUG_LEAK). gc.DEBUG_LEAK includes gc.DEBUG_COLLECTABLE, gc.DEBUG_UNCOLLECTABLE and gc.DEBUG_SAVEALL. gc.DEBUG_SAVEALL causes garbage-collected objects to be saved in gc.garbage for inspection. In normal circumstances they are collected.

5676d9fc-c7c7-45d2-a8dc-1cf3ef0ca594 commented 6 years ago

you are right. i realized later i actually had a leak in a com instantiated object, assumed it was a leak in the python and tried to find it using the gc module.

The gc documentation led me down the garden path.

QUOTE

gc.garbage A list of objects which the collector found to be unreachable but could not be freed (uncollectable objects).

UNQUOTE

i assumed:

csabella commented 6 years ago

Can this be closed as 'Not a Bug'?

5676d9fc-c7c7-45d2-a8dc-1cf3ef0ca594 commented 6 years ago

Yes. Thanks.

On 30 Jan 2018 8:31 PM, "Cheryl Sabella" \report@bugs.python.org\ wrote:

Cheryl Sabella \chekat2@gmail.com\ added the comment:

Can this be closed as 'Not a Bug'?

---------- nosy: +csabella


Python tracker \report@bugs.python.org\ \https://bugs.python.org/issue32045\