我有一个用于图像处理的应用程序,我发现自己通常分配 4000x4000 ushort 大小的数组,偶尔也会分配 float 等。目前,.NET 框架在这个应用程序中似乎是随机崩溃的,几乎总是出现内存不足错误。 32mb 并不是一个巨大的声明,但如果 .NET 正在产生内存碎片,那么如此大的连续分配很可能不会按预期运行。
有没有办法告诉垃圾收集器更积极,或者对内存进行碎片整理(如果这是问题所在)?我意识到存在 GC.Collect 和 GC.WaitForPendingFinalizers 调用,并且我已经在我的代码中大量使用它们,但我仍然遇到错误。可能是因为我正在调用大量使用 native 代码的 dll 例程,但我不确定。我已经检查了那个 C++ 代码,并确保我声明的任何内存都被删除了,但我仍然遇到这些 C# 崩溃,所以我很确定它不在那里。我想知道 C++ 调用是否会干扰 GC,使其留下内存,因为它曾经与 native 调用交互——这可能吗?如果可以,我可以关闭该功能吗?
编辑:这是一些会导致崩溃的非常具体的代码。根据this SO question ,我不需要在这里处理 BitmapSource 对象。这是原始版本,其中没有 GC.Collects。它通常在撤消过程的第 4 到 10 次迭代时崩溃。由于我使用的是 WPF,此代码替换了空白 WPF 项目中的构造函数。由于我在下面对@dthorpe 的回答中解释的限制以及 this SO question 中列出的要求,我对位图源进行了古怪的处理。 .
public partial class Window1 : Window {
public Window1() {
InitializeComponent();
//Attempts to create an OOM crash
//to do so, mimic minute croppings of an 'image' (ushort array), and then undoing the crops
int theRows = 4000, currRows;
int theColumns = 4000, currCols;
int theMaxChange = 30;
int i;
List<ushort[]> theList = new List<ushort[]>();//the list of images in the undo/redo stack
byte[] displayBuffer = null;//the buffer used as a bitmap source
BitmapSource theSource = null;
for (i = 0; i < theMaxChange; i++) {
currRows = theRows - i;
currCols = theColumns - i;
theList.Add(new ushort[(theRows - i) * (theColumns - i)]);
displayBuffer = new byte[theList[i].Length];
theSource = BitmapSource.Create(currCols, currRows,
96, 96, PixelFormats.Gray8, null, displayBuffer,
(currCols * PixelFormats.Gray8.BitsPerPixel + 7) / 8);
System.Console.WriteLine("Got to change " + i.ToString());
System.Threading.Thread.Sleep(100);
}
//should get here. If not, then theMaxChange is too large.
//Now, go back up the undo stack.
for (i = theMaxChange - 1; i >= 0; i--) {
displayBuffer = new byte[theList[i].Length];
theSource = BitmapSource.Create((theColumns - i), (theRows - i),
96, 96, PixelFormats.Gray8, null, displayBuffer,
((theColumns - i) * PixelFormats.Gray8.BitsPerPixel + 7) / 8);
System.Console.WriteLine("Got to undo change " + i.ToString());
System.Threading.Thread.Sleep(100);
}
}
}
现在,如果我明确调用垃圾收集器,我必须将整个代码包装在一个外部循环中以导致 OOM 崩溃。对我来说,这往往发生在 x = 50 左右:
public partial class Window1 : Window {
public Window1() {
InitializeComponent();
//Attempts to create an OOM crash
//to do so, mimic minute croppings of an 'image' (ushort array), and then undoing the crops
for (int x = 0; x < 1000; x++){
int theRows = 4000, currRows;
int theColumns = 4000, currCols;
int theMaxChange = 30;
int i;
List<ushort[]> theList = new List<ushort[]>();//the list of images in the undo/redo stack
byte[] displayBuffer = null;//the buffer used as a bitmap source
BitmapSource theSource = null;
for (i = 0; i < theMaxChange; i++) {
currRows = theRows - i;
currCols = theColumns - i;
theList.Add(new ushort[(theRows - i) * (theColumns - i)]);
displayBuffer = new byte[theList[i].Length];
theSource = BitmapSource.Create(currCols, currRows,
96, 96, PixelFormats.Gray8, null, displayBuffer,
(currCols * PixelFormats.Gray8.BitsPerPixel + 7) / 8);
}
//should get here. If not, then theMaxChange is too large.
//Now, go back up the undo stack.
for (i = theMaxChange - 1; i >= 0; i--) {
displayBuffer = new byte[theList[i].Length];
theSource = BitmapSource.Create((theColumns - i), (theRows - i),
96, 96, PixelFormats.Gray8, null, displayBuffer,
((theColumns - i) * PixelFormats.Gray8.BitsPerPixel + 7) / 8);
GC.WaitForPendingFinalizers();//force gc to collect, because we're in scenario 2, lots of large random changes
GC.Collect();
}
System.Console.WriteLine("Got to changelist " + x.ToString());
System.Threading.Thread.Sleep(100);
}
}
}
如果我在任何一种情况下对内存处理不当,如果有什么我应该用分析器发现的,请告诉我。这是一个非常简单的例程。
不幸的是,@Kevin 的回答似乎是正确的——这是 .NET 中的一个错误以及 .NET 如何处理大于 85k 的对象。这种情况让我觉得非常奇怪。 Powerpoint 是否可以在具有这种限制的 .NET 或任何其他 Office 套件应用程序中重写? 85k 在我看来并不是一个很大的空间,而且我还认为任何经常使用所谓“大”分配的程序在使用 .NET 时会在几天到几周内变得不稳定。
编辑:看起来 Kevin 是对的,这是 .NET GC 的限制。对于那些不想关注整个线程的人,.NET 有四个 GC 堆:gen0、gen1、gen2 和 LOH(大型对象堆)。 85k 或更小的所有内容都放在前三个堆之一中,具体取决于创建时间(从 gen0 移动到 gen1 再到 gen2,等等)。大于 85k 的对象被放置在 LOH 上。 LOH 从不 压缩,因此最终,我正在执行的类型分配最终会导致 OOM 错误,因为对象分散在该内存空间中。我们发现迁移到 .NET 4.0 确实在一定程度上帮助解决了这个问题,延迟了异常,但没有阻止它。老实说,这感觉有点像 640k 的障碍——85k 应该足以满足任何用户应用程序的要求(解释 .NET 中 GC 的讨论 this video)。郑重声明,Java 的 GC 不会表现出这种行为。
最佳答案
这里有一些文章详细介绍了大对象堆的问题。这听起来像是您可能遇到的情况。
大对象堆的危险:
http://www.simple-talk.com/dotnet/.net-framework/the-dangers-of-the-large-object-heap/
这是一个关于如何在大对象堆 (LOH) 上收集数据的链接:
http://msdn.microsoft.com/en-us/magazine/cc534993.aspx
据此,似乎没有办法压缩 LOH。我找不到任何更新的内容明确说明如何执行此操作,因此它似乎在 2.0 运行时中没有更改:
http://blogs.msdn.com/maoni/archive/2006/04/18/large-object-heap.aspx
处理这个问题的简单方法是尽可能制作小物体。您的另一个选择是只创建几个大对象并一遍又一遍地重复使用它们。这不是一个理想的情况,但它可能比重写对象结构更好。由于您确实说过创建的对象(数组)大小不同,这可能很困难,但它可以防止应用程序崩溃。
关于c# - 我如何让 .NET 积极地进行垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2860917/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack