﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
35279	Memory Leak with `prefetch_related`	Ken Tong	nobody	"Memory Leak after calling `queryset.prefetch_related()` or `prefetch_related_objects()`

To reproduce:

{{{
import gc
from django.db import models
from django.db.models import prefetch_related_objects


class Foo(models.Model):
    id = models.AutoField(primary_key=True)


class Bar(models.Model):
    id = models.AutoField(primary_key=True)
    foo = models.ForeignKey(Foo, on_delete=models.CASCADE)


def prepare_data():
    if Foo.objects.exists():
        return
    foo = Foo()
    foo.save()
    bar = Bar(foo=foo)
    bar.save()


def test1():
    # no prefetch
    for foo in Foo.objects.all():
        for bar in foo.bar_set.all():
            print(foo.id, bar.id)


def test2():
    # queryset.prefetch_related()
    for foo in Foo.objects.prefetch_related(""bar_set"").all():
        for bar in foo.bar_set.all():
            print(foo.id, bar.id)


def test3():
    # prefetch_related_objects()
    foo_list = list(Foo.objects.all())
    prefetch_related_objects(foo_list, ""bar_set"")
    for foo in foo_list:
        for bar in foo.bar_set.all():
            print(foo.id, bar.id)


def run():
    prepare_data()

    # warn up
    test1()
    test2()
    test3()

    gc.collect()

    gc.set_debug(gc.DEBUG_LEAK)

    gc.collect()
    print(f""baseline - garbage count: {len(gc.garbage)}"")

    test1()
    gc.collect()
    print(f""test1 - garbage count: {len(gc.garbage)}"")

    test2()
    gc.collect()
    print(f""test2 - garbage count: {len(gc.garbage)}"")

    test3()
    gc.collect()
    print(f""test3 - garbage count: {len(gc.garbage)}"")

    gc.set_debug(0)


run()
}}}


Output
{{{
1 1
1 1
1 1
baseline - garbage count: 0
1 1
test1 - garbage count: 0  # no memory leak
1 1
test2 - garbage count: 23  # 23 objects leaked
1 1
test3 - garbage count: 46  # another 23 objects leaked
}}}
"	Cleanup/optimization	closed	Database layer (models, ORM)	4.2	Normal	invalid	memory leak		Unreviewed	0	0	0	0	0	0
