【问题标题】:Threading in Pygame causing Memory leak [duplicate]Pygame中的线程导致内存泄漏
【发布时间】:2022-11-06 18:08:47
【问题描述】:

我正在创建一个小行星游戏。该游戏旨在长时间使用。

启动时(使用 pycharms 调试工具)我使用了大约 30.1 MB 的系统内存。但是我注意到,在运行时,它每秒增加大约 0.1 MB(固定 fps 为 60)。在测试并将 fps 设置为无限制时,我注意到内存使用量分别随着 fps 的增加而增加。

import pygame
import math
import random
import threading

class Main:
    def __init__(self):
        self.image = None
        self.Dimensions = 1000
        self.display = pygame.display.set_mode((self.Dimensions, self.Dimensions))
        self.fps = 60
        self.MainPage = True
        self.Game = False
        self.clock = pygame.time.Clock()
        pygame.init()
    def start(self):
        self.running = True
        self.character = Player()
        self.handler = EventHandler()
        self.display = pygame.display.set_mode((self.Dimensions, self.Dimensions))
        while self.running:
            self.event_list = pygame.event.get()
            for self.event in self.event_list:
                if self.event.type == pygame.QUIT:
                    self.running = False
                    pygame.display.quit()
                    pygame.quit()
                    quit()
            white = [255, 255, 255]
            self.display.fill(white)
            self.Dimensions = 1000
            self.clock.tick(self.fps)
            self.handler.spawn()
            self.handler.update()
            pygame.display.flip()
class Player:
    def __init__(self):
        self.Dimensions = Game.Dimensions
        self.x = self.Dimensions / 2
        self.y = self.Dimensions / 2
        self.looking_directions = 0
        self.velocity = 0
        self.image = "Pictures/Player.png"

class Asteroids():
    def __init__(self):
        self.size = 100
        self.x = random.choice(list(set([x for x in range(0, 9)]) - set(range(int(Game.Dimensions/5), int(Game.Dimensions*(4/5))))))
        self.y = random.choice(list(set([x for x in range(0, 9)]) - set(range(int(Game.Dimensions/5), int(Game.Dimensions*(4/5))))))
        self.velocity = random.uniform(1, 2)
        self.looking_direction = random.randrange(0, 360)
        self.picture = "Pictures/Asteroids.png"
        size = 75
        self.image = pygame.image.load(self.picture)
        self.image = pygame.transform.scale(self.image, (size, size))
        self.image = pygame.transform.rotate(self.image, self.looking_direction)
    def Update(self):
        
        Game.display.blit(self.image, (self.x, self.y))

class EventHandler():
    def __init__(self):
        self.asteroid_list = []
        self.tick = 0
        self.asteroid_cap = 15
    def spawn(self):
        self.tick += 1
        if len(self.asteroid_list) >= self.asteroid_cap:
            pass
        elif self.tick >= 60:
            temp_asteroid = Asteroids()
            self.asteroid_list.append(temp_asteroid)
            print("Asteroid created: " + str(len(self.asteroid_list)) + " currently alive")
            self.tick = 0
    def update(self):
        for current in self.asteroid_list:

            x = threading.Thread(target=current.Update)
            x.start()
        try:
            x.join()
        except:
            pass
if __name__ == "__main__":
    Game = Main()
    Game.start()

编辑:内存增加来自这个函数。但是现在我想知道如何改变这个改变这个函数,这样我就可以在不增加内存的情况下保持线程

    def update(self):
        for current in self.asteroid_list:
            x = threading.Thread(target=current.Update)
            y = threading.Thread(target=current.Drift)
            x.start()
            y.start()

        try:
            
            x.join()
            y.join()
        except:
            pass

我想保持线程(或高效的东西),因为根据我的经验,pygame 一次对多个图像进行 blitting 有点慢,所以使用循环,我可以尽快开始对它们进行 blitting 的过程,然后一旦它们都开始了,我调用 x.join() 所以无论如何,线程不会落后于导致视觉错误等的框架。

提前致谢

【问题讨论】:

  • edit您的问题创建minimal reproducible example。如果最小示例没有内存泄漏,恭喜!您可以通过逐步添加代码并修复泄漏位来解决您自己的问题。如果没有,社区可能会为您提供帮助。
  • @importrandom 谢谢你的建议。我不明白为什么我被否决了。我现在已经上传了包含内存泄漏的代码。不久前有人告诉我永远不要包含我的整个代码,因为它阻塞了帖子,人们不想通过整个代码来进行小内存泄漏
  • 您的事件处理程序在每次游戏循环迭代时为每个小行星创建一个线程,这可能是您增加内存使用的原因。我怀疑这是必要的。您还在每个循环中加载和转换图像,这是次优的。您应该在创建对象时加载一次图像。请查看pygame spritesgroups,它们让你做你想做的事变得更容易。
  • 顺便说一句:每个Asteroid 中的每个update() 都在重新加载、重新缩放和重新旋转位图。这是在浪费一个巨大的CPU 数量。加载位图一次,预缩放它。然后制作包含 /N/ 位图旋转的列表,如果您需要度数精度,甚至 360。然后Asteroid 对象只需要从列表中绘制适当的位图。更新将变为:window.blit( asteroid_images[ int( self.angle) ], ( self.x, self.y ) )
  • 你能解释一下你建议的列表部分吗?我已将位图加载移动到 Asteroids.__init__() 所以它只加载一次。我不明白你的意思by /N/ rotations of the bitmap

标签: python python-3.x memory-leaks pygame python-multithreading


【解决方案1】:

完全删除了线程。从问题并修复每个类实例的初始图像加载

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-23
    • 2021-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 1970-01-01
    • 2015-07-06
    相关资源
    最近更新 更多