我可以触发 JavaScript 的垃圾回收吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8032928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can I trigger JavaScript's garbage collection?
提问by Abhinav
I want to trigger JavaScript garbage collection. Is it possible? Why would I want to, or not want to, do this?
我想触发 JavaScript 垃圾收集。是否可以?为什么我想或不想这样做?
回答by Martin Andersson
I went out on a small journey to seek an answer to one of your questions: Is it possible?
我出去进行了一次小旅行,以寻求您的一个问题的答案:这可能吗?
People all over town are saying that deleting the references will do the trick. Some people say that wiping the object is an extra guarantee (example). So I wrote a script that will try every trick in the book, and I was astonished to see that in Chrome (22.0.1229.79) and IE (9.0.8112.16421), garbage collection doesn't even seem to work. Firefox (15.0.1) managed without any major drawbacks apart from one (see case 4f down below).
全城的人都说删除参考资料就行了。有人说擦拭物体是一种额外的保证(示例)。所以我写了一个脚本来尝试书中的每一个技巧,我很惊讶地看到在 Chrome (22.0.1229.79) 和 IE (9.0.8112.16421) 中,垃圾收集似乎不起作用。Firefox (15.0.1) 的管理没有任何重大缺陷,除了一个(见下面的案例 4f)。
In pseudo-code, the test goes something like this.
在伪代码中,测试是这样的。
Create a container, an array, that will hold objects of some sort. We'll call this container
Bertil
here on.Each and every object therein, as an element in Bertil, shall have his own array-container declared as a property. This array will hold a whole lot of bytes. We'll call any one of Bertil's elements, the object,
Joshua
. Each Joshua's byte array will be calledSmith
.Here's a mind map for you to lean back on:
Bertil
[Array of objects] ->Joshua
[Object] ->Smith
[Array of bytes] -> Unnamed [Bytes].When we've made a mess out of our available memory, hang around for a sec or two and then execute any one of the following "destruction algorithms":
4a. Throw a delete operand on the main object container, Bertil.
4b. Throw a delete operand on each and every object in that container, kill every Joshua alive.
4c. Throw a delete operand on each and every array of bytes, the Smiths.
4d. Assign NULL to every Joshua.
4e. Assign UNDEFINED to every Joshua.
4f. Manually delete each and every byte that any Joshua holds.
4g. Do all of the above in a working order.
创建一个容器,一个数组,将保存某种类型的对象。我们将
Bertil
在这里调用这个容器。其中的每个对象,作为 Bertil 中的一个元素,都应将其自己的数组容器声明为属性。这个数组将保存大量字节。我们将调用 Bertil 的任何一个元素,即对象,
Joshua
。每个 Joshua 的字节数组将被调用Smith
。这是您可以依赖的思维导图:
Bertil
[对象数组] ->Joshua
[对象] ->Smith
[字节数组] -> 未命名 [字节]。当我们把可用内存弄得一团糟时,停留一两秒钟,然后执行以下任何一种“破坏算法”:
4a. 在主对象容器 Bertil 上抛出一个删除操作数。
4b. 对该容器中的每个对象抛出一个删除操作数,杀死每个活着的约书亚。
4c。在每个字节数组 Smiths 上抛出一个删除操作数。
4天。为每个约书亚分配 NULL。
4e。将 UNDEFINED 分配给每个约书亚。
4f。手动删除任何约书亚持有的每个字节。
4克。按工作顺序执行上述所有操作。
So what happened?In case 4aand 4b, no browser's garbage collector (GC) kicked in. In case 4c to 4e, Firefox did kick in and displayed some proof of concept. Memory was reclaimed shortly within the minute. With current hardcoded default values on some of the variables used as test configuration, case 4fand 4ecaused Chrome to hang, so I can't draw any conclusions there. You are free to do your own testing with your own variables, links will be posted soon. IE survived case 4f and 4e but his GC was dead as usual. Unexpectedly, Firefox survived but didn't pass 4f. Firefox survived and passed 4g.
所以发生了什么事?在情况4a和4b 中,没有浏览器的垃圾收集器 (GC) 启动。在情况4c 到 4e 中,Firefox 确实启动并显示了一些概念证明。一分钟之内,记忆就被收回了。对于用作测试配置的某些变量的当前硬编码默认值,案例4f和4e导致 Chrome 挂起,因此我无法在那里得出任何结论。您可以使用自己的变量自由进行测试,链接将很快发布。IE 在案例 4f 和 4e 中幸存下来,但他的 GC 像往常一样死了。出乎意料的是,Firefox 活了下来,却没有通过 4f。Firefox 幸存下来并通过了 4g。
In all of the cases when a browser's GC failed to kick in, waiting around for at least 10 minutes didn't solve the problem. And reloading the entire page caused the memory footprint to double.
在浏览器的 GC 未能启动的所有情况下,等待至少 10 分钟并不能解决问题。重新加载整个页面会导致内存占用增加一倍。
My conclusion is that I must have made a horrible error in the code or the answer to your question is: No we can't trigger the GC. Whenever we try to do so we will be punished severely and we should stick our heads in the sand. Please I encourage you to go ahead, try these test cases on your own. Have a look in the code were comment on the details. Also, download the page and rewrite the script and see if you can trigger the GC in a more proper way. I sure failed and I can't for the life of me believe that Chrome and IE doesn't have a working garbage collector.
我的结论是我一定在代码中犯了一个可怕的错误,或者你的问题的答案是:不,我们不能触发 GC。每当我们试图这样做时,我们都会受到严厉的惩罚,我们应该把头埋在沙子里。我鼓励你继续,自己尝试这些测试用例。看看代码中的注释细节。另外,下载页面并重写脚本,看看是否可以以更合适的方式触发GC。我肯定失败了,我一生都无法相信 Chrome 和 IE 没有可用的垃圾收集器。
http://martinandersson.com/dev/gc_test/?case=1
http://martinandersson.com/dev/gc_test/?case=2
http://martinandersson.com/dev/gc_test/?case=3
http://martinandersson.com/dev/gc_test/?case=4
http://martinandersson.com/dev/gc_test/?case=5
http://martinandersson.com/dev/gc_test/?case=1
http://martinandersson.com/dev/gc_test/?case=2
http://martinandersson.com/dev/gc_test/?case=3
http://martinandersson.com/dev/gc_test/?case=4
http://martinandersson.com/dev/gc_test/?case=5
回答by masterspambot
You can trigger manually JavaScript garbage collector in IE and Opera, but it's not recommended, so better don't use it at all. I give commands more just for information purpose.
您可以在 IE 和 Opera 中手动触发 JavaScript 垃圾收集器,但不建议这样做,因此最好不要使用它。我更多地给出命令只是为了提供信息。
Internet Explorer:
IE浏览器:
window.CollectGarbage()
Opera 7+:
歌剧 7+:
window.opera.collect()
回答by jfriend00
Garbage collection runs automatically. How and when it runs and actually frees up unreferenced objects is entirely implementation specific.
垃圾收集自动运行。它如何以及何时运行并实际释放未引用的对象完全取决于实现。
If you want something to get freed, you just need to clear any references to it from your javascript. The garbage collector will then free it.
如果你想释放某些东西,你只需要从你的 javascript 中清除对它的任何引用。然后垃圾收集器将释放它。
If you explain why you even think you need to do this or want to do this and show us the relevant code, we might be able to help explain what your alternatives are.
如果您解释为什么您甚至认为您需要这样做或想要这样做并向我们展示相关代码,我们也许能够帮助解释您的替代方案。
回答by mixel
- Check your code for global variables. There may be data coming through an ajax call that is stored, and then referenced somewhere and you did not take this into account.
- As a solution, you should wrap huge data processing into an anonymous function call and use inside this call only local variables to prevent referencing the data in a global scope.
- Or you can assign to null all used global variables.
- Also check out this question. Take a look at the third example in the answer. Your huge data object may still be referenced by async call closure.
- 检查全局变量的代码。可能有数据通过存储的 ajax 调用传来,然后在某处引用,而您没有考虑到这一点。
- 作为解决方案,您应该将大量数据处理包装到匿名函数调用中,并在此调用中仅使用局部变量,以防止在全局范围内引用数据。
- 或者您可以将所有使用的全局变量分配为 null。
- 也看看这个问题。看一下答案中的第三个例子。您的巨大数据对象可能仍被异步调用闭包引用。
回答by Daniel Wahlberg
This answersuggests the following garbage collection request code for Gecko based browsers:
这个答案为基于 Gecko 的浏览器建议了以下垃圾收集请求代码:
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
回答by GullerYA
Came across this question and decided to share with my recent findings. I've looked to see a proper handling of a WeakMap in Chrome and it's actually looks okay:
遇到这个问题并决定分享我最近的发现。我已经在 Chrome 中看到了对 WeakMap 的正确处理,它实际上看起来没问题:
1) var wm = new WeakMap()
1) var wm = new WeakMap()
2) var d = document.createElement('div')
2) var d = document.createElement('div')
3) wm.set(d, {})
3) wm.set(d, {})
at this stage weak map holds the entry cause d is still referencing the element
在这个阶段,weak map 持有入口,因为 d 仍在引用元素
4) d = null
4) d = null
at this stage nothing references the element and it's weakly referenced object, and indeed after a couple of minutes entry disappeared and garbage collected.
在此阶段,没有任何内容引用该元素,并且它是弱引用对象,并且确实在几分钟后条目消失并收集了垃圾。
when did the same but appended the element to the DOM, it was not reclaimed, which is correct, removed from the DOM and still waiting for it to be collected :)
什么时候做了同样的事情但是将元素附加到 DOM,它没有被回收,这是正确的,从 DOM 中删除并仍在等待它被收集:)
回答by maelwyn
I was reading Trevor Prime's answer and it gave me a chuckle but then I realized he was on to something.
我正在阅读 Trevor Prime 的回答,它让我笑了起来,但后来我意识到他正在做某事。
- Reloading the page does 'garbage-collect'.
- location.reload() or alternatives to refresh page.
- JSON.parse/stringify and localStorage.getItem/setItem for persistence of needed data.
- iframes as reloading pages for user experience.
- 重新加载页面会“垃圾收集”。
- location.reload() 或替代刷新页面。
- JSON.parse/stringify 和 localStorage.getItem/setItem 用于持久化所需数据。
- iframes 作为用户体验的重新加载页面。
All you need to do is run your code in an iframe and refresh the iframe page while saving useful information into localStorage. You'll have to make sure the iframe is on the same domain as main page to access its DOM.
您需要做的就是在 iframe 中运行您的代码并刷新 iframe 页面,同时将有用的信息保存到 localStorage 中。您必须确保 iframe 与主页在同一个域中才能访问其 DOM。
You could do it without an iframe but user experience will no doubt suffer as the page will be visibly resetting.
您可以在没有 iframe 的情况下执行此操作,但用户体验无疑会受到影响,因为页面将明显重置。
回答by Trevor Prime
Yes, you can trigger garbage collection by re-loading the page.
是的,您可以通过重新加载页面来触发垃圾回收。
You might want to consider using a Factory Pattern to help re-use objects, which will greatly cut down on how many objects are created. Especially, if you are continuously creating objects that are the same.
您可能需要考虑使用工厂模式来帮助重用对象,这将大大减少创建的对象数量。特别是,如果您不断创建相同的对象。
If you need to read up on Factory Patterns then get yourself this book, "Pro Javascript Design Patterns" by Ross Harmes and Dustin Diaz and published by APress.
如果您需要阅读工厂模式,那么请为自己准备这本书,Ross Harmes 和 Dustin Diaz 合着并由 APress 出版的“Pro Javascript Design Patterns”。
回答by David Spector
If it is true that there is no way to trigger a GC, as implied by the other answers, then the solution would be for the appropriate browser standards group to add a new JavaScript function to window or document to do this. It is useful to allow the web page to trigger a GC at a time of its own choosing, so that animations and other high-priority operations (sound output?) will not be interrupted by a GC.
如果确实无法触发 GC,正如其他答案所暗示的那样,那么解决方案是让适当的浏览器标准组向窗口或文档添加新的 JavaScript 函数来执行此操作。允许网页在自己选择的时间触发 GC 很有用,这样动画和其他高优先级操作(声音输出?)不会被 GC 中断。
This might be another case of "we've always done it this way; don't rock the boat" syndrome.
这可能是“我们一直都是这样做的;不要乱动”综合症的另一个例子。
ADDED:
添加:
MDN documents a function "Components.utils.schedulePreciseGC" that lets a page schedule a GC sometime in the future with a callback function that is called when the GC is complete. This may not exist in browsers other than Firefox; the documentation is unclear. This function might be usable prior to animations; it needs to be tested.
MDN 记录了一个函数“Components.utils.schedulePreciseGC”,它允许页面在未来某个时间安排一个 GC,并在 GC 完成时调用回调函数。这在 Firefox 以外的浏览器中可能不存在;文件不清楚。此功能可能在动画之前可用;它需要进行测试。