如何让 Mono 中的垃圾收集器做任何有用的事情?这篇文章的底部是一个生成两个大字符串的简单 C# 测试程序。生成第一个字符串后,取消引用变量,退出作用域,并手动触发垃圾收集器。尽管如此,使用的内存并没有减少,并且在构造第二个字符串期间程序因内存不足异常而爆炸。
Unhandled Exception: OutOfMemoryException [ERROR] FATAL UNHANDLED EXCEPTION: System.OutOfMemoryException: Out of memory at (wrapper managed-to-native) string:InternalAllocateStr (int) at System.String.Concat (System.String str0, System.String str1) [0x00000] in :0 at GCtest.Main (System.String[] args) [0x00000] in :0
经过研究,我发现 Mono 的 --gc=sgen 开关使用不同的垃圾收集算法。更糟糕的是,生成了以下堆栈跟踪:
Stacktrace:
at (wrapper managed-to-native) string.InternalAllocateStr (int) <0xffffffff> at string.Concat (string,string) <0x0005b> at GCtest.Main (string[]) <0x00243> at (wrapper runtime-invoke) .runtime_invoke_void_object (object,intptr,intptr,intptr) <0xffffffff>
Native stacktrace:
0 mono-sgen 0x000bc086 mono_handle_native_sigsegv + 422 1 mono-sgen
0x0000466e mono_sigsegv_signal_handler + 334 2 libsystem_c.dylib
0x913c659b _sigtramp + 43 3 ???
0xffffffff 0x0 + 4294967295 4 mono-sgen
0x0020306d mono_gc_alloc_obj_nolock + 363 5 mono-sgen
0x0020394a mono_gc_alloc_string + 153 6 mono-sgen
0x001c9a10 mono_string_new_size + 147 7 mono-sgen
0x0022a6d1 ves_icall_System_String_InternalAllocateStr + 28 8 ???
0x004c450c 0x0 + 4998412 9 ???
0x004ceec4 0x0 + 5041860 10 ???
0x004c0f74 0x0 + 4984692 11 ???
0x004c1163 0x0 + 4985187 12 mono-sgen
0x00010164 mono_jit_runtime_invoke + 164 13 mono-sgen
0x001c5791 mono_runtime_invoke + 137 14 mono-sgen
0x001c7f92 mono_runtime_exec_main + 669 15 mono-sgen
0x001c72cc mono_runtime_run_main + 843 16 mono-sgen
0x0008c617 mono_main + 8551 17 mono-sgen
0x00002606 start + 54 18 ???
0x00000003 0x0 + 3Debug info from gdb:
/tmp/mono-gdb-commands.2aCwlD:1: Error in sourced command file: unable to debug self
Got a SIGSEGV while executing native code. This usually indicates a fatal error in the mono runtime or one of the native libraries used by your application.
/Users/fraser/Documents/diff-match-patch/csharp/GCtest.command: line 12: 41011 Abort trap: 6 mono --gc=sgen GCtest.exe
代码如下:
using System;
public class GCtest {
public static void Main(string[] args) {
Console.WriteLine("Memory: " + (GC.GetTotalMemory(true) / 1024) + " KB");
{
// Generate the first string.
string text1 = "hello old world.";
for (int i = 0; i < 25; i++) {
text1 = text1 + text1;
}
// Dereference variable.
text1 = null;
// Drop out of scope.
}
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Memory: " + (GC.GetTotalMemory(true) / 1024) + " KB");
// Generate the second string.
string text2 = "HELLO NEW WORLD!";
for (int i = 0; i < 25; i++) {
text2 = text2 + text2;
}
Console.WriteLine("Memory: " + (GC.GetTotalMemory(true) / 1024) + " KB");
}
}
最佳答案
那是 32 位单声道吗?我相信您所描述的行为是由这样一个事实引起的,即使用 Boehm GC,至少会保守地扫描堆栈。这意味着其上的值被视为指针。如果某个这样的值指向一个对象(或它的下级),那么这个对象将不会被收集。现在很清楚了,为什么大对象在这里有问题——它们可以很容易地填充 32 位进程的虚拟地址空间,我们很有可能堆栈中的某些值指向其中的某个地方并且整个对象没有被收集。这种讨厌的假指针的来源是什么?我最熟悉的是散列、随机值或日期/时间(通常 int 很低)。
How does one get the garbage collector in Mono to do anything useful?
您使用的方法是正确的,但我认为您遇到了上述问题。通常的程序不会受到太大影响,因为(如此)巨大的对象非常罕见。明天我还将在 64 位单声道上对其进行测试。
然而,自动出现的问题是为什么 Mono 项目不进行另一个 GC,这不会是保守的?如您所见,这种垃圾收集器是 sgen。我认为 sgen 的目的是,除了作为精确 收集器之外,它还可以压缩,这对于长时间运行的应用程序非常重要,并且它具有(有时)更好的性能。然而 sgen 仍处于测试阶段,我们可以观察到这里那里的崩溃。此外,精确堆栈扫描功能已在不同版本的 Mono 中打开和关闭,有时会出现一些回归,因此您可能会发现旧版本的 Mono 比新版本更好用。尽管如此,sgen 正在积极开发(因为可以在 github 上找到浏览提交历史记录)并且应该很快取代 Mono 中的默认垃圾收集器。这应该最终解决所描述的问题。
顺便说一句,例如,我的 Mono 版本(仍然是 32 位)通过 sgen 通过了这个测试:
$ mono --gc=sgen GCTest.exe
Memory: 4098 KB
Memory: 4140 KB
Memory: 1052716 KB
希望这对您有所帮助,如果有什么不清楚的地方可以询问(尤其是因为我的英语水平很差)。
编辑:
在我的 64 位机器上,Boehm 运行良好:
$ mono GCTest.exe
Memory: 132 KB
Memory: 280 KB
Memory: 1048860 KB
(自然也是 sgen)。在 Linux 上是 Mono 2.10.5。
关于c# - 在 Mono 中触发垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8764258/
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd
我有一个rubyonrails应用程序。我按照facebook的说明添加了一个像素。但是,要跟踪转化,Facebook要求您将页面置于达到预期结果时出现的转化中。即,如果我想显示客户已注册,我会将您注册后转到的页面作为成功对象进行跟踪。我的问题是,当客户注册时,在我的应用程序中没有登陆页面。该应用程序将用户带回主页。它在主页上显示了一条消息,所以我想看看是否有一种方法可以跟踪来自Controller操作而不是实际页面的转化。我需要计数的Action没有页面,它们是ControllerAction。是否有任何人都知道的关于如何执行此操作的gem、文档或最佳实践?这是进入布局文件的像素
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d
我想写一点“Deprecate-It”库并经常使用“method_added”回调。但是现在我注意到在包含模块时不会触发此回调。是否有任何回调或变通方法,以便在某些内容包含到自身时通知类“Foobar”?用于演示的小Demo:#IncludingModulswon'ttriggermethod_addedcallbackmoduleInvisibleMethoddefinvisible"Youwon'tgetacallbackfromme"endendclassFoobardefself.method_added(m)puts"InstanceMethod:'#{m}'addedto'
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用