当前位置:首页 > 内存 > 正文

cocos2djs内存泄露

  • 内存
  • 2024-06-10 06:46:25
  • 7910

一、JS内存泄漏与垃圾回收机制

内存生命周期:

程序需要内存才能运行。只要程序需要,操作系统就必须提供内存。

服务进程要持续运行,必须及时释放内存。否则,内存使用量将越来越多,轻则影响系统性能,重则导致进程崩溃。

内存泄漏案例:全局变量、未破坏的定时器和回调函数(setInterval)、闭包(外部函数中的变量被引用且无法释放)、DOM引用(元素被移除),但仍有引用)元素)

识别无用变量的方法有两种:标记-清除和引用计数。

当变量进入环境时,它被标记为“进入环境”。当变量离开环境时,它被标记为“退出环境”。

您可以使用“进入环境”和“退出环境”变量列表来跟踪变量的更改。您还可以在变量进入和退出环境时翻转和记录特殊位。。环境。

如果声明变量并为其分配引用类型的值,则对该值的引用次数为1。如果将相同的值分配给另一个变量,则对该值的引用次数为1。计数加一。如果包含对某个值的引用的变量获取不同的值,则对该值的引用数会减少1。一旦某个值的引用次数达到0,该值占用的内存空间就可以被回收。下次垃圾收集器运行时,零引用计数值占用的内存将被释放。

如何观察内存泄漏?

经验法则:如果连续5次垃圾回收后内存使用量增加;则存在内存泄漏。这就需要实时显示内存使用情况。

前面说过,及时清除引用非常重要。然而,如果你不小心忘记了什么,你可能就记不住那么多了,内存泄漏是很常见的。

当您创建新引用时,声明哪些引用必须手动清除,哪些引用可以忽略。当其他引用消失时,垃圾收集机制会释放内存。这大大减轻了程序员的负担,因为他们只需要清除主要引用即可。


二、如何解决cocos2d-x内存增长/泄漏的问题首先,尝试检测使用内存的程序段中的内存泄漏是良好的编码实践。一旦程序变得稳定,在检测内存泄漏时,这无疑会增加故障排除的复杂性和难度。对于使用内存分配的函数,请务必使用您要使用的函数,以便在使用完毕后可以释放它。堆内存:malloc\realloc------freenew\new[]------------delete\delete[]GlobalAlloc------GlobalFree特别注意数组对象内存泄漏-MyPointEX*pointArray=newMyPointEX[100];删除形式:delete[]pointArrayResourceLeak:使用系统资源前,应仔细阅读使用方法,防止误用或忘记释放系统资源。让我们看一下MSDN中创建字体的示例:RECTrect;HBRUSHhBrush;FONThFont;hdc=BeginPaint(hWnd,&ps);hFont=reateFont(48,0,0,0,FW_DONTCARE,FALSE,TRUE,FALSE,DEFAULT_CHARSET,OUT_OUTLINE_PRECIS)。,CLIP_DEFAULT_PRECIS,CLEARTYPE_QUALITY,VARIABLE_PITCH,TEXT("影响"));SelectObject(hdc,hFont);SetRect(&rect,100,100,700,200);SetTextColor(hdc,RGB(255,0,0));DrawText(hdc,TEXT("DrawingTextwithImpact"),-1,&rect,DT_NOCLIP);DeleteObject(hFont);EndPaint(hWnd,&ps);数据源网络


三、如何避免JavaScript的内存泄露使用Chrome查找内存泄漏
泄漏基本上有两种类型:周期性内存增长引起的泄漏和偶发性内存泄漏。显然,间歇性内存泄漏很容易被发现,而且通常很容易被忽视。有时内存泄漏可以被视为优化问题,而重复出现的泄漏则被视为需要修复的错误。
以Chrome文档中的代码为例:
varx=[];functioncreateSomeNodes(){vardiv,i=100,frag=DocumentFragment();for(;i>0;i--){div=Element("div");Child(TextNode(i+"-"+newDate().toTimeString()));Child(div);}文档。getElementById("nodes").appendChild(frag);}functiongrow(){(newArray(1000000).join('x'));createSomeNodes();setTimeout(grow,1000);}
执行grow时,会创建div节点并将其插入到DOM中,并将一个大数组分配给全局变量。使用上述工具可以检测到内存的稳定增加。
查找循环增长的内存
时间线代码很擅长做到这一点。在Chrome中打开示例,打开DevTools,切换到Timeline,检查内存并单击录制按钮,然后单击页面上的TheButton。一段时间后停止记录并查看结果:
图像中的Nodes(绿线)和JSheap(蓝线)两个迹象显示内存泄漏。节点稳定增长,不减少,这是一个显着的信号。
JSheap的内存使用量也在稳步增长。由于垃圾收集器的影响,不太容易找到。该图显示内存使用量上升和下降。事实上,JSheap的大小比以前更大了。换句话说,使垃圾收集器继续收集内存,它仍然会周期性地泄漏内存。
确认存在内存泄漏后,我们找到原因。
保存两个快照
切换到ChromeDevTools中的配置文件选项卡,刷新页面,页面刷新完成后,单击TakeHeapSnapshot将快照保存为基线。然后再次单击该按钮,等待几秒钟并保存第二个快照。
在过滤菜单中选择Summary,在右侧选择在Snapshot1和Snapshot2之间分配的Object,或者在过滤菜单中选择Comparison,即可看到比较列表。
在这个例子中很容易发现内存泄漏。查看(字符串)的SizeDeltaConstructor,8MB,58个新对象。新对象已分配但未释放,占用8MB。
如果扩展(string)构造函数,您将看到许多单独的内存分配。在评选个人奖项时,我们应注意以下几点。
我们选择的分配是与窗口对象的x变量关联的数组的一部分。这里显示了从巨大对象到无法回收的根(窗口)的整个路径。我们已经找到了潜在的泄漏及其来源。
我们的例子比较简单,只有少量的DOM节点被泄露,使用上面提到的快照可以很容易地检测到。对于较大的网站,Chrome还提供RecordHeapAllocations功能。
Recordheapallocations发现内存泄漏
返回ChromeDevTools中的配置文件选项卡,然后单击RecordHeapAllocations。该工具运行时,注意顶部的蓝线,它代表内存分配每秒都有大量的内存分配。它运行几秒钟然后停止。
上图中你可以看到该工具的王牌:选择一个特定的时间线,你可以看到该时间段内的内存分配情况。如果您选择尽可能靠近顶部的时间轴,则下面的列表仅显示三个构造函数:一个是泄漏最多的(字符串),下一个是关联的DOM分配,最后一个是文本构造函数(中的文本)DOM叶节点)。
从列表中选择HTMLDivElement构造函数,然后选择Allocationsstack。
现在你知道元素被分配到哪里了(grow->createSomeNodes)仔细观察图中的时间线,发现HTMLDivElement构造函数被调用了很多次,这意味着内存已经被调用了。被占用并且不能被GC回收,我们确切地知道这些对象被分配到哪里(createSomeNodes)。让我们回到代码本身并讨论如何修复内存泄漏。
另一个有用的功能
在堆分配的结果区域中选择分配。
该视图呈现与内存分配相关的函数列表。我们立即看到NoenNode的增长和创建。当您选择增长时,查看有问题的对象构造函数,并清楚地看到(string)、HTMLDivElement和Text被泄漏。
结合上面提到的工具,可以轻松发现内存泄漏。