Что вызывает утечку памяти в моем коде при использовании kivy? - PullRequest
0 голосов
/ 16 марта 2019

Я беспокоюсь о проблеме с названием. Я показал ниже мой код, сокращенный согласно его структуре кода. Код предполагает сохранение в качестве имени файла "revival_memory_leak.py". Утечка памяти произошла по команде return Rectangle(size=...) и т. Д., Обнаруженной модулем tracemalloc. Есть ли какой-нибудь совет, которым я могу освободить память экземпляра сгенерированного класса Rectangle?

from kivy.uix.widget import Widget
from kivy.graphics import Color, Line, Rectangle
import tracemalloc
from kivy.app import App
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.config import Config

width = 400
height = 300
Config.set('graphics', 'width', str(width))
Config.set('graphics', 'height', str(height))


class MyClass(Widget):

    def __init__(self):
        super().__init__()
        self.cnt_of_loop = 0
        self.gid = "1111"  # Group ID
        self.step_width = 10
        self.pos_x = 0

    def start(self):
        # start loopmethod()
        Clock.schedule_interval(self.loop, 0.01)

    def get_rectangle(self):
        self.pos_x += self.step_width
        if self.pos_x >= width:
            self.pos_x = self.step_width
        # This method returns customized every time kivy.graphics.Rectangle class instance
        # The below code seems to cause one of memory leak
        return Rectangle(size=(10, 30), pos=(self.pos_x, height / 2), group=self.gid)  # generate a Rectangle instance with gid "1111"

    def update_canvas(self):
        self.canvas.remove_group(self.gid)  # clear all canvas items with gid:"1111"
        self.canvas.add(Color(1, 0, 1, self.gid))
        self.canvas.add(self.get_rectangle())  # add new canvas one more items

    def loop(self, dt):
        """ This method called repeatedly and infinity """

        self.update_canvas()
        """ Show difference between used memory and it at step 10"""
        if self.cnt_of_loop == 10:
            self.snapshot1 = tracemalloc.take_snapshot()
        if self.cnt_of_loop > 200:
            snapshot2 = tracemalloc.take_snapshot()
            top_stats = snapshot2.compare_to(self.snapshot1, 'lineno')

            print("[ Top 10 differences]")
            for stat in top_stats[:10]:
                print(stat)
        self.cnt_of_loop += 1


class MyApp(App):
    def build(self):
        # return MyClass()
        a = MyClass()
        a.start()
        return a


if __name__ == '__main__':
    tracemalloc.start()
    MyApp().run()
  • Результат:

    • Обратите внимание на строки, написанные как "revival_memory_leak.py". Команда, написанная в строках внимания, показалась увеличенной. Два нижних «10 лучших отличий» показывают результаты ранней и поздней стадии. Например, «revival_memory_leak.py:37», который указывает на строку 37 файла revival_memory_leak.py, объем памяти был увеличен до 276 КБ с 179 КБ. Почему бы не освободить память? Я думал, что память освобождает объект рисования (например, Rectangle), когда вызывается метод remove_group.
  • «ранняя стадия» потребления памяти

[ Top 10 differences]
revival_memory_leak.py:37: size=179 KiB (+177 KiB), count=2421 (+2396), average=76 B
python3.6/site-packages/kivy/core/window/__init__.py:1343: size=177 KiB (+176 KiB), count=1205 (+1190), average=150 B
revival_memory_leak.py:33: size=140 KiB (+136 KiB), count=4430 (+4345), average=32 B
python3.6/tracemalloc.py:113: size=90.1 KiB (+90.1 KiB), count=1049 (+1049), average=88 B
python3.6/site-packages/kivy/weakmethod.py:56: size=75.8 KiB (+75.0 KiB), count=1078 (+1066), average=72 B
revival_memory_leak.py:53: size=57.8 KiB (+57.8 KiB), count=919 (+919), average=64 B
python3.6/tracemalloc.py:117: size=57.0 KiB (+57.0 KiB), count=912 (+912), average=64 B
revival_memory_leak.py:51: size=55.8 KiB (+55.8 KiB), count=893 (+893), average=64 B
python3.6/site-packages/kivy/cache.py:211: size=18.8 KiB (+18.4 KiB), count=300 (+295), average=64 B
python3.6/site-packages/kivy/clock.py:581: size=14.0 KiB (+11.6 KiB), count=198 (+185), average=72 B
  • «поздняя стадия» потребления памяти
[ Top 10 differences ]
python3.6/site-packages/kivy/core/window/__init__.py:1343: size=283 KiB (+283 KiB), count=1854 (+1839), average=156 B
revival_memory_leak.py:37: size=276 KiB (+274 KiB), count=3732 (+3707), average=76 B
revival_memory_leak.py:33: size=187 KiB (+182 KiB), count=6432 (+6347), average=30 B
python3.6/site-packages/kivy/weakmethod.py:56: size=114 KiB (+113 KiB), count=1623 (+1611), average=72 B
revival_memory_leak.py:53: size=93.5 KiB (+93.5 KiB), count=1490 (+1490), average=64 B
python3.6/tracemalloc.py:117: size=92.6 KiB (+92.6 KiB), count=1482 (+1482), average=64 B
python3.6/tracemalloc.py:113: size=90.4 KiB (+90.4 KiB), count=1052 (+1052), average=88 B
revival_memory_leak.py:51: size=90.0 KiB (+90.0 KiB), count=1440 (+1440), average=64 B
python3.6/site-packages/kivy/cache.py:211: size=34.9 KiB (+34.6 KiB), count=559 (+554), average=64 B
python3.6/tracemalloc.py:387: size=16.2 KiB (+16.2 KiB), count=226 (+226), average=73 B

1 Ответ

0 голосов
/ 24 марта 2019

Кажется, я решил свою проблему, используя класс InstructionGroup вместо непосредственного добавления графических элементов в canvas.Спасибо за ваше сотрудничество.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...