开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第29天,点击查看活动详情
前言
对于大部分语言,开发者可以不用关注垃圾回收的问题,因为执行环境会负责在代码执行时进行垃圾回收从而管理内存。但是 C 和C++除外。执行环境会自动进行内存管理实现内存分配和限制资源回收。
垃圾回收
垃圾回收都是周期性执行的。垃圾回收的基本思路就是:没有使用的变量就释放它所占用的内存。程序执行时经常会需要一些变量,而这些变量就会在内存中占据空间。但是当变量不再使用时就会进行标记然后释放所占据的空间就可以释放出来供后面使用。垃圾回收也并非完美,程序未必就能正确识别变量是不再使用的。
垃圾回收常用的两种标记策略:
标记清理
基本的设计思路如下所示:
- 当程序声明一个变量时,该变量就会在上下文中被标记。
- 之后就会将所有变量以及被其他引用的的变量标记去掉。
- 最后再加上标记。此时增加的标记都是无法被访问到的。
- 随后就是一次内存清理,清除所有带标记的变量并回收它们的内存。
引用计数
基本的设计思路如下所示:
- 对每个值都记录被引用的次数。
- 垃圾回收程序对引用次数为 0 的将进行清除并回收内存
相比较标记清理策略:引用计数会存在问题。比如两个对象如果是循环引用那么再引用次数都是为2且将永远都不会为空。这样就会导致它们占据的内存永远都不会被释放。
性能问题
垃圾回收是周期性执行的,如果存在内存中分配大量的变量就可能造成性能损失。因为垃圾回收程序遇到很多变量时它就需要频繁运行。当然在程序上开发者可以让内存占用量尽量的小,还可以在没有使用时直接释放其饮用,比如直接设置为 null。
所以垃圾回收程序虽然开发者不用太关注,但是在平常开发的过程中有也应当尽量避免在内存中声明太多变量导致垃圾回收程序在回收过程需要消耗太多时间和性能在回收上,而应当尽量的让内用占用量保持一个小的值。
其他有效提高垃圾回收的性能方法有:
- 尽量使用 let 和 const ,而不是用 var,因为可以让来集回收程序尽早回收内存
- V8 编译 Js时会利用隐藏类,所以对一些对象如果是相同隐藏类可以通过共享来提高性能
- 避免出现内存泄露
- 间接控制促发垃圾回收的条件,那就是合理使用内存。比如对于频繁修改的对象尽量不使用动态创建。