一、安装中的坑
从mono官网下载源码包mono-3.4.0.tar.bz2直接编译安装后,报错:
/usr/bin/install: cannot stat `targets/Microsoft.Portable.Common.targets': No such file or directory
进行以下操作,解决之:
#> cd ${MONO_SOURCE}/mcs/tools/xbuild/targets
#> cp Microsoft.Portable.CSharp_4.0.targets Microsoft.Portable.Common.targets
#> vi Microsoft.Portable.Common.targets
在vi中将Microsoft.Portable.Common.targets文件中的这行:
<Import Project="$(MSBuildToolsPath)/Microsoft.CSharp.targets" />删除,
然后保存退出。接着进入Mono的源码目录进行配置、编译、安装。
./configure 如果按默认参数配置则最大堆大小不能超过3GB,打开--with-large-heap=yes开关则可以超过3GB。
./configure --with-large-heap=yes
二、关于MONO_GC_PARAMS
mono中的内存分为三块:nursery, major heap和large object space
nursery主要存放新生成的小对象和被pinned住的小对象
major heap是老年代,主要存放在gc中从nursery移过来的对象
large object space存放大于8K的对象,SGen-GC把大对象直接分配在操作系统的内存页上,垃圾回收时直接释放内存回操作系统
MONO_GC_PARAMS需要被设置成环境变量,多个参数用逗号隔开,可以使用以下参数:
max-heap-size:最大堆大小
major:老年代垃圾回收策略,默认只使用单CPU进行垃圾回收,有以下值:`marksweep', `marksweep-conc', `marksweep-par', 'marksweep-fixed' or 'marksweep-fixed-par'
major-heap-size:老年代堆大小,默认为512M,该参数必须和major参数一起使用,单独使用会报错
minor:新生代垃圾回收策略,有以下值:`simple' or `split'
nursery-size:新生代大小,默认为4M,采用的是copying collection, 值必须是2的幂
soft-heap-limit:当内存使用小于该值会较少进行垃圾回收,大于该值则会有更多的垃圾回收次数
stack-mark:线程堆栈扫描策略。有两个值:precise, conservative。SGen垃圾回收器默认使用precise
evacuation-threshold:内存碎片阈值。取值范围[0 - 100],默认66
wbarrier: 按照官方文档的说法, major collection会扫描整个堆,而nursery collection只会扫描新生代,为了避免冲突,需要追踪从老年代指向新生代的任何引用,mono支持两种数据结构来保持追踪:cardtable 和 remset。我在mono3.4上测试提示不识别wbarrier参数,奇怪了。。。
完整示例:
export MONO_GC_PARAMS=max-heap-size=6g,major=marksweep-par-fixed,major-heap-size=3g,nursery-size=1g,stack-mark=precise,evacuation-threshold=66
关于mono垃圾回收有两篇官方文档可以参考:
Generational GC:http://www.mono-project.com/Generational_GC
Working With SGen:http://www.mono-project.com/Working_With_SGen
三、关于mono性能分析
使用--profile选项可以产生性能监控日志:
mono --profile=log hello.exe
产生的日志非常大,我测试了几秒就产生了五百多兆的日志,可以加上nocalls选项去掉对方法调用的监控。
要想以上语句正常运行需要先设置环境变量:
export LD_LIBRARY_PATH=/opt/mono/mono34/lib
如果在程序中使用了P/Invoke导入dll,则还要设置环境变量:DYLD_LIBRARY_PATH
生成报告:
mprof-report output.mlpd
使用文本编辑器打开生成的output.report,性能报告有以下几个部分:
Mono log profiler data
JIT summary
GC summary
Allocation summary 按对象占用的内存大小从大到小进行排序
Method call summary 按方法调用的时间长短从大到小进行排序
Metadata summary
Exception summary
Thread summary
关于mono性能分析有一篇官方文档可以参考:
Profiler:http://www.mono-project.com/Profiler