首页 \ 问答 \ JavaScript闭包如何被垃圾回收(How JavaScript closures are garbage collected)

JavaScript闭包如何被垃圾回收(How JavaScript closures are garbage collected)

我已经记录了以下Chrome错误 ,这导致我的代码中出现了许多严重和非明显的内存泄漏:

(这些结果使用Chrome开发工具的内存分析器 ,它运行GC,然后对不收集垃圾的所有内容进行堆快照。)

在下面的代码中, someClass实例是垃圾回收(不错):

var someClass = function() {};

function f() {
  var some = new someClass();
  return function() {};
}

window.f_ = f();

但在这种情况下不会收集垃圾(不好):

var someClass = function() {};

function f() {
  var some = new someClass();
  function unreachable() { some; }
  return function() {};
}

window.f_ = f();

和相应的截图:

Chromebug的屏幕截图

似乎一个闭包(在这种情况下, function() {} )保持所有对象“活着”,如果该对象被同一上下文中的任何其他闭包引用,无论该闭包本身甚至是否可达。

我的问题是在其他浏览器(IE 9+和Firefox)中关闭垃圾收集。 我非常熟悉webkit的工具,例如JavaScript堆分析器,但是我不了解其他浏览器的工具,所以我无法测试。

在这三种情况中,哪些IE9 +和Firefox垃圾收集 someClass 实例?


I've logged the following Chrome bug, which has led to many serious and non-obvious memory leaks in my code:

(These results use Chrome Dev Tools' memory profiler, which runs the GC, and then takes a heap snapshot of everything not garbaged collected.)

In the code below, the someClass instance is garbage collected (good):

var someClass = function() {};

function f() {
  var some = new someClass();
  return function() {};
}

window.f_ = f();

But it won't be garbage collected in this case (bad):

var someClass = function() {};

function f() {
  var some = new someClass();
  function unreachable() { some; }
  return function() {};
}

window.f_ = f();

And the corresponding screenshot:

screenshot of Chromebug

It seems that a closure (in this case, function() {}) keeps all objects "alive" if the object is referenced by any other closure in the same context, whether or not if that closure itself is even reachable.

My question is about garbage collection of closure in other browsers (IE 9+ and Firefox). I am quite familiar with webkit's tools, such as the JavaScript heap profiler, but I know little of other browsers' tools, so I haven't been able to test this.

In which of these three cases will IE9+ and Firefox garbage collect the someClass instance?


原文:https://stackoverflow.com/questions/19798803
更新时间:2023-07-22 12:07

最满意答案

从InnoDB中删除数据是您可以请求的最昂贵的操作。 正如您已经发现查询本身不是问题 - 大多数都将针对相同的执行计划进行优化。

虽然可能很难理解为什么所有案例的删除都是最慢的,但是有一个相当简单的解释。 InnoDB是一个事务性存储引擎。 这意味着如果您的查询中途中止,则所有记录仍将保留,就好像没有发生任何事情。 一旦完成,所有的都将在同一时刻消失。 在DELETE期间,连接到服务器的其他客户端将看到记录,直到您的DELETE完成。

为了实现这一点,InnoDB使用了一种名为MVCC(Multi Version Concurrency Control)的技术。 它基本上做的是为每个连接提供整个数据库的快照视图,就像在事务的第一个语句开始时一样。 为了实现这一点,InnoDB内的每个记录都可以有多个值 - 每个快照一个。 这也是为什么InnoDB上的COUNTing需要一些时间 - 这取决于当时看到的快照状态。

对于您的DELETE事务,根据查询条件识别的每个记录都被标记为删除。 由于其他客户端可能同时访问数据,因此无法立即将其从表中删除,因为它们必须查看其各自的快照以保证删除的原子性。

一旦所有记录都被标记为删除,则事务被成功提交。 即使这样,在DELETE事务之前所有其他使用快照值的事务也已经结束的情况下,它们不能立即从实际数据页中删除。

所以实际上你的3分钟并不是那么慢,考虑到所有的记录必须被修改,以便以交易安全的方式来准备它们去除。 可能您会在声明运行时“听到”您的硬盘工作。 这是由于访问所有行。 为了提高性能,您可以尝试增加服务器的InnoDB缓冲池大小,并尝试在DELETE时限制对数据库的其他访问,从而也减少InnoDB每个记录维护的历史版本数。 随着额外的内存,InnoDB可能能够将表(主要)读入内存,并避免了一些磁盘寻找时间。


Deleting data from InnoDB is the most expensive operation you can request of it. As you already discovered the query itself is not the problem - most of them will be optimized to the same execution plan anyway.

While it may be hard to understand why DELETEs of all cases are the slowest, there is a rather simple explanation. InnoDB is a transactional storage engine. That means that if your query was aborted halfway-through, all records would still be in place as if nothing happened. Once it is complete, all will be gone in the same instant. During the DELETE other clients connecting to the server will see the records until your DELETE completes.

To achieve this, InnoDB uses a technique called MVCC (Multi Version Concurrency Control). What it basically does is to give each connection a snapshot view of the whole database as it was when the first statement of the transaction started. To achieve this, every record in InnoDB internally can have multiple values - one for each snapshot. This is also why COUNTing on InnoDB takes some time - it depends on the snapshot state you see at that time.

For your DELETE transaction, each and every record that is identified according to your query conditions, gets marked for deletion. As other clients might be accessing the data at the same time, it cannot immediately remove them from the table, because they have to see their respective snapshot to guarantee the atomicity of the deletion.

Once all records have been marked for deletion, the transaction is successfully committed. And even then they cannot be immediately removed from the actual data pages, before all other transactions that worked with a snapshot value before your DELETE transaction, have ended as well.

So in fact your 3 minutes are not really that slow, considering the fact that all records have to be modified in order to prepare them for removal in a transaction safe way. Probably you will "hear" your hard disk working while the statement runs. This is caused by accessing all the rows. To improve performance you can try to increase InnoDB buffer pool size for your server and try to limit other access to the database while you DELETE, thereby also reducing the number of historic versions InnoDB has to maintain per record. With the additional memory InnoDB might be able to read your table (mostly) into memory and avoid some disk seeking time.

相关问答

更多
  • UPDATE速度要快得多。 当你UPDATE ,表格记录正在被新数据重写。 所有这些都必须在INSERT再次完成。 当你DELETE ,索引应该更新(记住,你删除整行,不仅需要修改列),数据块可能会移动(如果你点击PCTFREE限制)。 同样,删除和添加新更改会记录auto_increment上的ID,因此如果这些记录的关系会被破坏,或者需要更新。 我会去UPDATE 。 这就是为什么你应该更喜欢INSERT ... ON DUPLICATE KEY UPDATE而不是REPLACE 。 前一个是在违反密钥 ...
  • 我已经发布了这个解决方案 ,但是当address超出一定长度时,它是在Range(address)抛出错误的上下文中。 但现在主题严格来说是删除多行的最快方法,我认为必须坚持实际删除行(即保留格式,公式,公式引用......) 因此,我将在此处再次发布该解决方案(在“按地址删除”方法的标题下)以及第二个(“按排序删除”方法),这要快得多(第一个需要20秒,第二个需要一些0) ,2秒处理大约40k行,即删除20k行) 两个解决方案在OP For icount = endRow To 3 Step -2之后略微 ...
  • 从InnoDB中删除数据是您可以请求的最昂贵的操作。 正如您已经发现查询本身不是问题 - 大多数都将针对相同的执行计划进行优化。 虽然可能很难理解为什么所有案例的删除都是最慢的,但是有一个相当简单的解释。 InnoDB是一个事务性存储引擎。 这意味着如果您的查询中途中止,则所有记录仍将保留,就好像没有发生任何事情。 一旦完成,所有的都将在同一时刻消失。 在DELETE期间,连接到服务器的其他客户端将看到记录,直到您的DELETE完成。 为了实现这一点,InnoDB使用了一种名为MVCC(Multi Vers ...
  • 你甚至不需要为这个操作使用awk grep已经足够了: $ more file1 file2 :::::::::::::: file1 :::::::::::::: ID,NAME,ADDRESS 11,PP,LONDON 12,SS,BERLIN 13,QQ,FRANCE 14,LL,JAPAN :::::::::::::: file2 :::::::::::::: ID,NAME,ADDRESS 11,PP,LONDON 12,SS,BERLIN 13,QQ,FRANCE 16,WW,DUBAI $ ...
  • 我不认为你可以在一个查询中轻松地做到这一点,不是没有使用游标,但你可以将操作分成两部分,如下所示: --update action update a set a.id = b.id, a.match =1 from _persons a inner join _personals b on a.social = b.social or a.taxnumber = b.taxnumber --delete / insert action declare @RowCount as integer sel ...
  • 对于初学者,在工作表中添加一列并插入匹配功能。 这将告诉您相应搜索值的行号。 #N / A将出现在不匹配的行中。 您可以使用宏录制器自动填充“匹配”列,以RC格式保存公式,然后将它们复制到工作表的底部。 现在遍历匹配行列以查找#N / A 例: Dim aCell as range Dim aRange as range dim tWS as worksheet dim lrow as long Application.calculation = xlmanual set tWS = thisworkbo ...
  • 你很近。 尝试使用exists : delete from T1 where exists (select 1 from t2 where t1.user_id = t2.user_id and t1.level_id = t2.level_id ); You are pretty close. Try using exists: delete from T1 where exists ...
  • 取决于有多少数据,我会用暴力方式来做。 将所有负的总行选入临时表 使用游标遍历每一行,然后查询数据库中的单个匹配项(在时间戳,订单号或任何主键上可能使用max(),删除那个“匹配”行。 然后删除所有负面的行 毫无疑问,你可以使用一个子查询并在一个语句中完成它,但是当我弄清楚并测试它时,我将使用上面的方法完成这项工作:) depending on how much data there is, I would just do it the brute force way. select all the neg ...
  • 尝试这个 DELETE final FROM final LEFT JOIN journal ON final.accession=journal.accession WHERE journal.accession IS NOT NULL; 或这个 DELETE FROM final USING final, journal WHERE final.accession=journal.accession; final - 表将删除行 journal - 存在检查记 ...
  • 尝试: DELETE FROM tableB WHERE ctid IN ( SELECT BB.ctid FROM ( SELECT a, b, c, count(*) cnt FROM tablea GROUP BY a, b, c ) AA JOIN ( SELECT ctid, a, b, c, row_number() over (partition by a,b,c) cnt ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。