Ну, моно это здорово, но насколько я вижу, оно нестабильно. Это работает, но дает сбой, когда вы даете моно процессу серьезную работу.
TL; DR - не используйте моно, если вы:
- использовать AppDomains (Assembly Load \ Unload) в многопоточных средах
- Не может выдержать модель «дай-не-провал»
- Случайные события с большой нагрузкой во время выполнения процесса
Итак, факты.
Мы используем mono-2.6.7 (.net v 3.5) на RHEL5, Ubuntu, и, на мой взгляд, это самая стабильная версия, созданная Novell. У него есть проблема с Unloading AppDomains (segfaults), однако, это происходит очень редко, и это, безусловно, приемлемо (для нас).
Ладно. Но если вы хотите использовать функции .net 4.0, вам нужно переключиться на версии 2.10.x или 3.x, и вот тут начинаются проблемы.
По сравнению с 2.6.7 новые версии просто недопустимы. Я написал простое приложение для стресс-теста для тестирования моно установок.
Это здесь, с инструкциями по использованию: https://github.com/head-thrash/stress_test_mono
Он использует рабочие потоки пула потоков. Работник загружает DLL в AppDomain и пытается выполнить некоторую математическую работу. Некоторые работы многопоточные, некоторые одиночные. Почти вся работа связана с процессором, хотя есть некоторые операции чтения файлов с диска.
Результаты не очень хорошие. Фактически для версии 3.0.12:
- Sgen GC обрабатывает ошибки практически мгновенно
- Моно с Бёмом живет дольше (от 2 до 5 часов), но в итоге сегфолты
Как уже упоминалось выше, sgen gc просто не работает (моно собран из исходного кода):
* Assertion: should not be reached at sgen-scan-object.h:111
Stacktrace:
Native stacktrace:
mono() [0x4ab0ad]
/lib/x86_64-linux-gnu/libpthread.so.0(+0xfcb0) [0x2b61ea830cb0]
/lib/x86_64-linux-gnu/libc.so.6(gsignal+0x35) [0x2b61eaa74425]
/lib/x86_64-linux-gnu/libc.so.6(abort+0x17b) [0x2b61eaa77b8b]
mono() [0x62b49d]
mono() [0x62b5d6]
mono() [0x5d4f84]
mono() [0x5cb0af]
mono() [0x5cb2cc]
mono() [0x5cccfd]
mono() [0x5cd944]
mono() [0x5d12b6]
mono(mono_gc_collect+0x28) [0x5d16f8]
mono(mono_domain_finalize+0x7c) [0x59fb1c]
mono() [0x596ef0]
mono() [0x616f13]
mono() [0x626ee0]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x7e9a) [0x2b61ea828e9a]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d) [0x2b61eab31ccd]
Что касается Boehm Segfauls - например (Ubuntu 13.04, моно построен из источника):
mono: mini-amd64.c:492: amd64_patch: Assertion `0' failed.
Stacktrace:
at <unknown> <0xffffffff>
at System.Collections.Generic.Dictionary`2.Init (int,System.Collections.Generic.IEqualityComparer`1<TKey>) [0x00012] in /home/bkmz/my/mono/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:264
at System.Collections.Generic.Dictionary`2..ctor () [0x00006] in /home/bkmz/my/mono/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:222
at System.Security.Cryptography.CryptoConfig/CryptoHandler..ctor (System.Collections.Generic.IDictionary`2<string, System.Type>,System.Collections.Generic.IDictionary`2<string, string>) [0x00014] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/Crypto
Config.cs:582
at System.Security.Cryptography.CryptoConfig.LoadConfig (string,System.Collections.Generic.IDictionary`2<string, System.Type>,System.Collections.Generic.IDictionary`2<string, string>) [0x00013] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/CryptoCo
nfig.cs:473
at System.Security.Cryptography.CryptoConfig.Initialize () [0x00697] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:457
at System.Security.Cryptography.CryptoConfig.CreateFromName (string,object[]) [0x00027] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:495
at System.Security.Cryptography.CryptoConfig.CreateFromName (string) [0x00000] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:484
at System.Security.Cryptography.RandomNumberGenerator.Create (string) [0x00000] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/RandomNumberGenerator.cs:59
at System.Security.Cryptography.RandomNumberGenerator.Create () [0x00000] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/RandomNumberGenerator.cs:53
at System.Guid.NewGuid () [0x0001e] in /home/bkmz/my/mono/mcs/class/corlib/System/Guid.cs:492
Или (RHEL5, моно взят из rpm здесь ftp://ftp.pbone.net/mirror/ftp5.gwdg.de/pub/opensuse/repositories/home%3A/vmas%3A/mono-centos5 )
Assertion at mini.c:3783, condition `code' not met
Stacktrace:
at <unknown> <0xffffffff>
at System.IO.StreamReader.ReadBuffer () [0x00012] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.IO/StreamReader.cs:394
at System.IO.StreamReader.Peek () [0x00006] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.IO/StreamReader.cs:429
at Mono.Xml.SmallXmlParser.Peek () [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/Mono.Xml/SmallXmlParser.cs:271
at Mono.Xml.SmallXmlParser.Parse (System.IO.TextReader,Mono.Xml.SmallXmlParser/IContentHandler) [0x00020] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/Mono.Xml/SmallXmlParser.cs:346
at System.Security.Cryptography.CryptoConfig.LoadConfig (string,System.Collections.Generic.IDictionary`2<string, System.Type>,System.Collections.Generic.IDictionary`2<string, string>) [0x00021] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptog
raphy/CryptoConfig.cs:475
at System.Security.Cryptography.CryptoConfig.Initialize () [0x00697] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:457
at System.Security.Cryptography.CryptoConfig.CreateFromName (string,object[]) [0x00027] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:495
at System.Security.Cryptography.CryptoConfig.CreateFromName (string) [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:484
at System.Security.Cryptography.RandomNumberGenerator.Create (string) [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/RandomNumberGenerator.cs:59
at System.Security.Cryptography.RandomNumberGenerator.Create () [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/RandomNumberGenerator.cs:53
at System.Guid.NewGuid () [0x0001e] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System/Guid.cs:483
at System.Runtime.Remoting.RemotingServices.NewUri () [0x00020] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:356
at System.Runtime.Remoting.RemotingServices.Marshal (System.MarshalByRefObject,string,System.Type) [0x000ba] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:329
at System.AppDomain.GetMarshalledDomainObjRef () [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System/AppDomain.cs:1363
Оба сбоя так или иначе связаны с логикой AppDomains, поэтому вы должны держаться подальше от них в моно.
Кстати, протестированная программа работала 24 часа на Windows-машине в MS .NET 4.5 env без сбоев.
Итак, в заключение я бы хотел сказать - используйте моно с осторожностью. Это работает с первого взгляда, но может легко потерпеть неудачу всякий раз. Вы останетесь с кучей основных дампов и большой потерей веры в проекты с открытым исходным кодом.