预防模拟器中的内存泄漏#
当在 Python 对象中注册 C++ 回调时,Isaac Sim 模拟器中可能会发生内存泄漏。当类中的回调函数与其关联的 Python 对象保持引用时会发生这种情况。结果是,Python 的垃圾回收无法回收与这些对象相关联的内存,从而阻止了相应的 C++ 对象被销毁。随着时间的推移,这可能导致内存泄漏和资源使用量增加。
为了防止 Isaac Sim 模拟器中的内存泄漏,务必在向模拟器注册回调时使用弱引用。这可以确保在不再需要时可以对 Python 对象进行垃圾回收,从而避免内存泄漏。Python 标准库中的 weakref 模块可用于此目的。
例如,考虑一个具有需要向模拟器注册的回调函数 on_event_callback 的类。如果在传递回调时对 MyClass 对象使用强引用,则会增加 MyClass 对象的引用计数。这会防止在不再需要时对 MyClass 对象进行垃圾回收,即不会调用 __del__ 析构函数。
import omni.kit
class MyClass:
def __init__(self):
app_interface = omni.kit.app.get_app_interface()
self._handle = app_interface.get_post_update_event_stream().create_subscription_to_pop(
self.on_event_callback
)
def __del__(self):
self._handle.unsubscribe()
self._handle = None
def on_event_callback(self, event):
# do something with the message
要解决此问题,关键是在注册回调时使用弱引用。虽然这种方法会使代码变得冗长,但它确保在不再使用时可以对 MyClass 对象进行垃圾回收。以下是修改后的代码:
import omni.kit
import weakref
class MyClass:
def __init__(self):
app_interface = omni.kit.app.get_app_interface()
self._handle = app_interface.get_post_update_event_stream().create_subscription_to_pop(
lambda event, obj=weakref.proxy(self): obj.on_event_callback(event)
)
def __del__(self):
self._handle.unsubscribe()
self._handle = None
def on_event_callback(self, event):
# do something with the message
在这个修改后的代码中,当注册回调时使用弱引用 weakref.proxy(self) ,使得 MyClass 对象可以被正确地垃圾回收。
通过遵循这种模式,您可以防止内存泄漏,并保持更高效和稳定的模拟。