此问题已在新的 chrome 版本(版本 35.0.1916.114)中修复
在 chrome for mac osx 中,CanvasRenderingContext2D#getImageData 函数会造成内存泄漏,我该如何避免这个问题,这是测试用例和结果,它只是发生了在 chrome 浏览器中,safari 是可以的
<!DOCTYPE html>
<html>
<head>
<title>CanvasRenderingContext2D#getImageData bug in chrome</title>
<script type="text/javascript">
var g;
function init(){
g = document.getElementById('canvas').getContext('2d');
g.fillStyle = "blue";
g.fillRect(10, 10, 100, 100);
g.fillStyle = "green";
g.fillRect(60, 60, 100, 100);
}
function getImageData(){
var i = 0;
while(i++ < 100){
var c = g.getImageData(0,0,1000, 1000);
delete c;
}
}
function toDataURL(){
var i = 0;
while(i++ < 100){
var c = g.canvas.toDataURL();
delete c;
}
}
</script>
</head>
<body onload="init()">
<button onclick="getImageData()">call getImageData 100 times - then memory will grow, can't GC</button>
<button onclick="toDataURL()">call toDataURL 100 times - it is OK</button><br>
<canvas id='canvas' width='600px' height='500px'/>
</body>
</html>
最佳答案
您的问题不在于 getImageData 函数。保存 getImageData 的变量的分配方式造成了泄漏。
问题是 delete c 会失败(删除不影响变量名)并且浏览器会自动返回 false。
尝试使用 尝试在 c = null 代替。for 循环之外声明 c 变量,以避免在循环的每个步骤中重新创建变量。
修改后的代码:
function getImageData(){
var i = 0;
var c;
while(i++ < 100){
c = g.getImageData(0,0,1000, 1000);
// c = null; // <= check UPDATE to see why this doesn't work as expected
}
}
function toDataURL(){
var i = 0;
var c;
while(i++ < 100){
c = g.canvas.toDataURL();
// c = null; // <= check UPDATE to see why this doesn't work as expected
}
}
我在同一个浏览器中完全尝试了代码,并使用开发人员工具中的内存配置文件,我可以看到垃圾收集器完全清除了内存。
在开发者工具中检查内存时间线(Ctrl+Shift+i)。
要启用内存配置文件,您需要使用标志 --enable-memory-info 启动 Chrome。
正如我在评论中所说,垃圾回收通过回收不再可达的内存块(对象)来工作。
当函数返回时,c 指向的对象自动可用于垃圾回收,因为没有任何东西引用它。
对于 null 的工作原理也存在误解。将对象引用设置为 null 不会使对象“空化”。它将对象引用设置为空。
因此,在这种情况下,分配用于存储每个 getImageData 信息的内存将保留在那里,直到函数返回。由于 image data 是一个非常大的对象,并且 Canvas 尺寸越大,它就越大,在巨大的循环中(假设 500 次或以上,这取决于机器)会导致内存溢出函数返回并触发垃圾收集器。
我推荐以下文章:Writing Fast, Memory-Efficient JavaScript .它解释得很好并且易于阅读。
解决方案!!!
现在我们知道垃圾收集器只有在函数返回后才会被触发,我想到的一个解决方案是延迟调用getImageData的函数一小部分毫秒。这样我们可以保证函数在每次调用 getImageData 后返回。
我尝试了下面的代码,它甚至可以运行 10000 次迭代!花费大量时间完成,但它完成并且没有内存泄漏!)
自己试试:
<!DOCTYPE html>
<html>
<head>
<title>CanvasRenderingContext2D#getImageData bug fixed</title>
<script type="text/javascript">
var g;
function init(){
g = document.getElementById('canvas').getContext('2d');
g.fillStyle = "blue";
g.fillRect(10, 10, 100, 100);
g.fillStyle = "green";
g.fillRect(60, 60, 100, 100);
}
function getImageData(){
var c = g.getImageData(0,0,1000, 1000);
}
var total = 0;
var iterations = 100;
function test(){
var i = 0;
while(i++ < iterations){
setTimeout(function(){
getImageData();
total++;
//console.log(total);
if(total == iterations){
alert("" + total+" getImageData functions were completed!!!")
}
}, 0.01); // defer
}
alert("" + (i-1) + " iterations completed. Wait for the return of all getImageData");
}
</script>
</head>
<body onload="init()">
<button onclick="test()">call getImageData several times</button><br>
<canvas id='canvas' width='600px' height='500px'/>
</body>
</html>
关于用于 mac OSX 的 Chrome 浏览器中 HTML5 Canvas getImageData 的 javascript 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16758020/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.
当我使用has_one时,它工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290
我正在学习http://ruby.railstutorial.org/chapters/static-pages上的RubyonRails教程并遇到以下错误StaticPagesHomepageshouldhavethecontent'SampleApp'Failure/Error:page.shouldhave_content('SampleApp')Capybara::ElementNotFound:Unabletofindxpath"/html"#(eval):2:in`text'#./spec/requests/static_pages_spec.rb:7:in`(root)'
我正在尝试将一个简单的CSV文件读入HTML表格以在浏览器中显示,但我遇到了麻烦。这就是我正在尝试的:Controller:defshow@csv=CSV.open("file.csv",:headers=>true)end查看:输出:NameStartDateEndDateQuantityPostalCode基本上我只获取标题,而不会读取和呈现CSV正文。 最佳答案 这最终成为最终解决方案:Controller:defshow#OpenaCSVfile,andthenreaditintoaCSV::Tableobjectforda
我想用Nokogiri解析HTML页面。页面的一部分有一个表,它没有使用任何特定的ID。是否可以提取如下内容:Today,3,455,34Today,1,1300,3664Today,10,100000,3444,Yesterday,3454,5656,3Yesterday,3545,1000,10Yesterday,3411,36223,15来自这个HTML:TodayYesterdayQntySizeLengthLengthSizeQnty345534345456563113003664354510001010100000344434113622315