【问题标题】:Python Memory leak using Yocto使用 Yocto 的 Python 内存泄漏
【发布时间】:2015-10-01 07:59:00
【问题描述】:

我在树莓派上运行一个 python 脚本,它不断检查Yocto 按钮,当它被按下时,它将来自不同传感器的数据放入数据库中。

不断运行的代码 sn-p 是:

#when all set and done run the program
Active = True
while Active:
    if ResponseType == "b":
        while Active:
            try:
                if GetButtonPressed(ResponseValue):
                    DoAllSensors()
                    time.sleep(5)
                else:
                    time.sleep(0.5)
            except KeyboardInterrupt:
                Active = False
            except Exception, e:
                print str(e)
                print "exeption raised continueing after 10seconds"
                time.sleep(10)

GetButtonPressed(ResponseValue) 如下所示:

def GetButtonPressed(number):
    global buttons
    if ModuleCheck():
        if buttons[number - 1].get_calibratedValue() < 300:
            return True
    else:
        print "module not online"
    return False


def ModuleCheck():
    global moduleb
    return moduleb.isOnline()

我不太确定可能出了什么问题。但大约需要一个小时,RPI 才会耗尽内存。

内存大小不断增加,每15分钟左右才按一次按钮。

这已经告诉我问题一定出在上面显示的代码中。

【问题讨论】:

  • 使用 Python 内存分析,如 Heapy,确定泄漏内存的去向 smira.ru/wp-content/uploads/2011/08/heapy.html
  • 泄漏是在 yocto 库中,所以我不得不创建一个解决方法来每隔一段时间重置它,以防止它崩溃,直到我得到不同的解决方案
  • 我觉得这是报告错误的好日子:)
  • 我做了,并且已经收到他们正在处理的回复!真是美好的一天

标签: python memory-leaks yocto


【解决方案1】:

问题在于 yocto_api.YAPI 对象将继续在其 _DataEvents dict(类范围属性)中累积 _Event 对象直到您调用 YAPI.YHandleEvents。如果您不使用 API 的回调,很容易认为(我做了几个小时)您不需要调用它。 API 文档在这一点上根本不清楚:

如果您的程序包含重要的循环,您可能希望包含对该函数的调用,以确保库处理通信通道上模块推送的信息。这不是绝对必要的,但它可以提高库对以下命令的反应性。

在我决定定期轮询我自己的代码中的传感器之前,我尝试了一些 API 级别的回调,并且有可能在其中启用了某些设置,导致这些事件累积。如果不是这样,我无法想象他们为什么会说调用 YHandleEvents 是“不是绝对必要的”,除非他们在瑞士制造具有无限 RAM 的 ARM 设备。

这是一个神奇的静态方法,无论如何你都应该定期调用它。我每五秒钟这样做一次,这是在完全不加载系统的情况下解决问题。会累积不需要的事件的 API 代码对我来说仍然有异味,但该继续前进了。

#noinspection PyUnresolvedReferences
@staticmethod
def HandleEvents(errmsgRef=None):
    """
    Maintains the device-to-library communication channel.
    If your program includes significant loops, you may want to include
    a call to this function to make sure that the library takes care of
    the information pushed by the modules on the communication channels.
    This is not strictly necessary, but it may improve the reactivity
    of the library for the following commands.

    This function may signal an error in case there is a communication problem
    while contacting a module.

    @param errmsg : a string passed by reference to receive any error message.

    @return YAPI.SUCCESS when the call succeeds.

    On failure, throws an exception or returns a negative error code.
    """
    errBuffer = ctypes.create_string_buffer(YAPI.YOCTO_ERRMSG_LEN)

    #noinspection PyUnresolvedReferences
    res = YAPI._yapiHandleEvents(errBuffer)
    if YAPI.YISERR(res):
        if errmsgRef is not None:
            #noinspection PyAttributeOutsideInit
            errmsgRef.value = YByte2String(errBuffer.value)
        return res

    while len(YAPI._DataEvents) > 0:
        YAPI.yapiLockFunctionCallBack(errmsgRef)
        if not (len(YAPI._DataEvents)):
            YAPI.yapiUnlockFunctionCallBack(errmsgRef)
            break

        ev = YAPI._DataEvents.pop(0)
        YAPI.yapiUnlockFunctionCallBack(errmsgRef)
        ev.invokeData()
    return YAPI.SUCCESS

【讨论】:

    猜你喜欢
    • 2021-07-02
    • 2012-12-02
    • 2011-12-13
    • 2014-02-26
    • 2010-11-27
    • 2016-06-11
    • 2015-02-15
    • 1970-01-01
    • 2021-12-04
    相关资源
    最近更新 更多