mono的gc问题

mono的gc一直 使用 conservative gc..可见其文档的描述。是一种较为落后的实现,没有分代。在最近的2.8版本中多了

一种sgen的新gc..据称性能不错..原来的gc一直有precise stack scanning的问题。在一些stack上分配的对象存在无法收集的可能性。

 

前天看到一文:

http://flyingfrogblog.blogspot.com/2010/07/mono-24-still-leaking-like-sieve.html

 

需要凸墙...

 

作者用了一个简单的代码来证实这种memory leak的存在。我用c#改写了,代码如下:

 

public class MainS
    {
        public static void Main(string[] args)
        {
            for(var i = 0; i!=30; ++i)
            {
                var t = new Dictionary<int,int>();               
                for(var j = 0; j!=10000000; ++j)
                {
                   
                    t[j] = j;
                }
                Console.WriteLine(string.Format("{0},{1}",t.Count,i));
                //GC.Collect();
            }
            Console.WriteLine("haha");
        }
    }

 

此段代码在 mono 默认的gc上无法执行,会报outofmemory的错误..在新的sgen gc上勉强可以运行一阵子,但是最终会报sgen内部的一些错误。如果想要正确运行。那么可以把注释的部分打开 。。或者加入t.Clear()。这样在sgen gc下可以正常运行。在原有的gc依然不行。。

 

此段代码在注释掉gc.collect下在ms .net 3.5, .net 4.0均可以正常运行。现在看来mono的gc虽然有进步但是还不尽人意。。

 

出于好奇,我在python也实现了同样的代码,也没有任何问题。

 

据roadmap称,mono 2.10在gc方面将会有比较大的改进,希望如此。

 

测试环境: ubuntu10.04 32 bit, mono 2.8.2

                    windows 7 64 bit, .net 4.0, .net 3.5

 

有趣的是,如果把i 和 j的值 互换并不会出现问题。。看起来似乎mono的gc对 stack的大量对象存在回收的问题...

Mono采用了Bohem GC机制管理内存分配,Unity在其使用的Mono代码中,加入了内存分配的监控,所有的Alloc和GC函数都注入了Profiler的回调 [^1]。 ### 原理 在Mono的SGen垃圾回收机制里,对于内存分配有不同的处理方式。大对象(超过8K bytes,即SGEN_MAX_SMALL_OBJ_SIZE)被视为large object,这类对象不经过nursery和major heap,而是直接从操作系统申请内存,使用完后释放回操作系统,实现可参见`mono_sgen_los_alloc_large_inner()` [^2]。 ### 使用场景 MonoGC Alloc在程序运行过程中,当需要为新对象分配内存时就会触发。例如在创建新的变量、实例化对象等操作时,都会涉及到内存分配,也就是GC Alloc的使用场景。如调用`mono_compile_create_var`函数为Mono编译过程创建变量时,会根据给定的类型和操作码分配适当的寄存器,这其中就包含了内存分配的操作 [^3]。 ### 优化方法 从性能优化角度来看,可通过分帧处理来优化GC Alloc带来的性能问题。如在创建对象时,没使用分帧前可能出现性能下降到掉帧的情况,使用分帧处理后性能有所提高。示例代码如下: ```csharp public void CreateNormalBoll(uint day, long number) { index = 0; StartCoroutine(CreateNormalBollIE(day, number)); } int index = 0; // 每帧生成1000个 private IEnumerator CreateNormalBollIE(uint day, long number) { for (int i = 0; i < number; i++) { index++; normal_bolls.Add(new NormalBoll(day)); if (index % 1000 == 0) { yield return null; } } } ``` 通过这种分帧创建对象的方式,避免了短时间内大量的内存分配操作,从而减少了GC的压力 [^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值