[.net] 모노는 프라임 타임 준비가 되셨습니까? [닫은]

누구든지 대규모 또는 중간 규모 프로젝트에서 오픈 소스 .NET 구현 인 Mono를 사용 했습니까? 실제 프로덕션 환경에 적합한 지 궁금합니다. 안정적이고 빠르며 호환되며 사용하기에 충분합니까? 프로젝트를 Mono 런타임으로 이식하는 데 많은 노력이 필요합니까, 아니면 Microsoft 런타임을 위해 이미 작성된 코드를 가져와 실행할 수있을 정도로 실제로 호환됩니까?



답변

고려해야 할 몇 가지 시나리오가 있습니다. (a) 기존 응용 프로그램을 이식하고 Mono가이 작업에 충분한 지 궁금한 경우; (b) 새 코드를 작성하기 시작했으며 Mono가 충분히 성숙한 지 알고 싶습니다.

첫 번째 경우 Mono Migration Analyzer 도구 (Moma)를 사용하여 응용 프로그램이 Mono에서 얼마나 멀리 실행되는지 평가할 수 있습니다. 평가가 플라잉 색상으로 돌아 오면 테스트 및 QA를 시작하여 배송 준비를해야합니다.

평가에서 Mono의 시맨틱에서 누락되었거나 현저하게 다른 기능을 강조 표시하는 보고서가 다시 표시되면 코드를 적용, 재 작성할 수 있는지 또는 최악의 경우 응용 프로그램이 기능을 축소하여 사용할 수 있는지 여부를 평가해야합니다.

사용자 제출 (이것은 메모리에서 온)을 기반으로 한 Moma 통계에 따르면 약 50 %의 응용 프로그램이 기본적으로 작동합니다. 약 25 %는 약 일주일의 일 (리팩토링, 적응)이 필요하고 다른 15 %는 코드를 다시 실행하면 나머지는 Win32에 엄청나게 묶여 있기 때문에 이식을 귀찮게 할 가치가 없습니다. 그 시점에서, 당신은 0에서 시작하거나 사업 결정으로 코드를 이식하기 위해 노력할 것입니다.

처음부터 시작하는 경우 Mono에있는 API 만 사용하므로 상황이 훨씬 간단합니다. 지원되는 스택 (.NET 2.0과 LINQ 및 System.Core를 포함한 3.5의 모든 핵심 업그레이드 및 모든 모노 크로스 플랫폼 API)을 유지하는 한 괜찮습니다.

가끔씩 모노 또는 버그로 버그가 발생할 수 있으며, 그 문제를 해결해야 할 수도 있지만 다른 시스템과는 다릅니다.

이식성 : ASP.NET 응용 프로그램은 Win32에 거의 의존하지 않으며 SQL 서버 또는 기타 널리 사용되는 데이터베이스 (Mon과 함께 번들로 제공되는 데이터베이스 공급자가 많음)를 사용하기 때문에 이식하기가 더 쉽습니다.

Windows.Forms 포팅은 개발자가 .NET 샌드 박스를 피하고 브레인을 P / Invoke하여 wParam에서 BCD 형식으로 인코딩 된 두 베 지어 포인트로 표현되는 커서 깜박임 속도를 변경하는 데 유용한 항목을 구성하기 때문에 때때로 까다로워집니다. 아니면 그런 쓰레기.


답변

최대 .NET 4.0까지 광범위하게 적용되며 .NET 4.5 API의 일부 기능도 포함하지만 API가 더 이상 사용되지 않거나 새로운 대안이 만들어 지거나 범위가 너무 커서 구현하지 않기로 선택한 몇 가지 영역이 있습니다. 큰. Mono에서는 다음 API를 사용할 수 없습니다.

  • Windows Presentation Foundation
  • Windows Workflow Foundation (두 버전 중 하나가 아님)
  • 엔터티 프레임 워크
  • 표준 웹 서비스 스택에 대한 WSE1 / WSE2 “애드온”

또한 WCF 구현은 Silverlight가 지원하는 것으로 제한됩니다.

특정 프로젝트를 확인하는 가장 쉬운 방법은 MoMA (Mono Migration Analyzer )를 실행하는 것 입니다. 이점은 Mono (있는 경우)를 사용하지 못하게하여 작업의 우선 순위를 지정할 수있는 문제를 Mono 팀에 알릴 수 있다는 것입니다.

최근에 SubSonic에서 MoMA를 실행했으며 Nullable 유형의 이상한 사용이라는 한 가지 문제 만 발견했습니다. 그것은 큰 코드베이스이므로 적용 범위가 상당히 인상적입니다.

모노는 여러 상용 및 공개 소스 제품 에서 활발히 사용되고 있습니다 . Wikipedia 및 Mozilla Developer Center와 같은 일부 대규모 응용 프로그램에서 사용되며 Sansa MP3 플레이어와 같은 내장 응용 프로그램에서 사용되고 수천 개의 게시 된 게임을 지원합니다.

언어 수준 에서 Mono 컴파일러는 C # 5.0 언어 사양을 완벽하게 준수합니다 .


답변

데스크톱 측면에서 GTK #을 사용하기로 약속하면 Mono가 훌륭하게 작동합니다. Windows.Forms 구현은 여전히 ​​약간 버그가 있지만 (예 : TrayIcon이 작동하지 않음) 먼 길을 왔습니다. 게다가 GTK #는 Windows Forms보다 더 나은 툴킷입니다.

웹 측에서 Mono는 대부분의 사이트를 완벽하게 실행할 수 있도록 충분한 ASP.NET을 구현했습니다. 여기서 어려움은 아파치에 mod_mono가 설치된 호스트를 찾거나 호스트에 대한 쉘 액세스 권한이있는 경우 직접 수행하는 것입니다.

어느 쪽이든, 모노는 훌륭하고 안정적입니다.

크로스 플랫폼 프로그램을 작성할 때 기억해야 할 주요 사항 :

  • Windows 대신 GTK #을 사용하십시오.
  • 파일 이름을 올바르게 입력하십시오
  • 사용 Path.Separator하는 대신 하드 코딩으로 "\"도 사용 Environment.NewLine대신에 "\n".
  • Win32 API에 대한 P / Invoked 호출을 사용하지 마십시오.
  • Windows 레지스트리를 사용하지 마십시오.

답변

나는 개인적으로 프라임 타임 환경에서 모노를 사용합니다. 기가 바이트의 udp / tcp 데이터 처리 관련 작업을 처리하는 모노 서버를 실행했는데 더 행복 할 수 없었습니다.

특이한 점이 있으며 가장 성가신 것은 Mono의 현재 상태로 인해 msbuild 파일을 “빌드”할 수 없다는 것입니다.

  • MonoDevelop (IDE)는 부분적인 msbuild를 지원하지만, 기본적으로 단순한 hello-world (사용자 정의 빌드 작업, $ (SolutionDir)와 같은 동적 “속성”, 실제 구성은 몇 가지 사망자를 넘어서서 어떤 “REAL”빌드 conf에서 멈출 것입니다. 끝)
  • xbuild 되어 있어야 모노 – 공급 – msbuild를-완벽하게 호환 빌드 시스템은 실제로 그렇게 명령 줄에서 구축의 매우 “정통”상태 인 GUI를 사용하는 것보다 더 나쁜 경험을 더욱 끔찍한입니다 Linux 환경을위한 통합 …

한 번 / 실제로 물건을 얻는 동안, 다음과 같이 지원되어야하는 코드조차도 광야를 볼 수 있습니다.

  • 컴파일러는 특정 구문에서 지루해집니다.
  • 그리고 더 진보 된 새로운 .NET 클래스가 예기치 않은 쓰레기를 던집니다 (XLinq 누구입니까?)
  • 일부 미성숙 런타임 “기능”(x64에서 3GB 힙 제한 … WTF!)

그러나 헤빙은 일반적으로 말하기가 매우 빨리 작동하기 시작하며 솔루션 / 해결 방법이 풍부하다고 말했다 .

일단 당신이 그 초기 허들을 극복했다면, 나의 경험은 그 모노 ROCKS이며, 매번 반복 할 때마다 계속 나아지고 있습니다.

나는 모노로 실행하고 매일 300GB의 데이터를 처리하는 서버를 가지고 있었으며, 많은 p / invoke를 사용하고 일반적으로 “최첨단”모노에서도 5-6 개월 동안 일을 계속하고 있습니다.

도움이 되었기를 바랍니다.


답변

허용 된 답변에 대한 권장 사항이 약간 오래되었습니다.

  • Windows Forms 구현은 이제 꽤 좋습니다. ( Windows Forms 응용 프로그램 인 Paint.net 포트는 Paint-Mono 를 참조하십시오 . 필요한 것은 P-Invoke 및 지원되지 않는 일부 시스템 호출에 대한 에뮬레이션 계층이었습니다.)
  • Path.Seperator뿐만 아니라 Path.Seperator는 경로와 파일 이름을 결합합니다.
  • Windows 레지스트리는 응용 프로그램에서 데이터를 저장하고 검색하는 데만 사용하는 한 괜찮습니다 (예 : 기본적으로 Mono 응용 프로그램의 레지스트리이므로 Windows에 대한 정보를 얻을 수 없음).

답변

WPF를 사용하고 싶다면 Mono가 현재 구현할 계획이 없습니다.

http://www.mono-project.com/WPF


답변

글쎄, 모노는 훌륭하지만 내가 볼 수있는 한 불안정합니다. 작동하지만 모노 프로세스에 심각한 작업을 제공하면 오류가 발생합니다.

TL; DR-다음과 같은 경우 모노를 사용하지 마십시오.

  • 다중 스레드 환경에서 AppDomain (Assembly Load \ Unload) 사용
  • ‘let-it-fail’모델을 유지할 수 없습니다
  • 프로세스 실행 중 가끔 과부하 이벤트 발생

사실.

우리는 RHEL5, Ubuntu에서 mono-2.6.7 (.net v 3.5)을 사용하며, 필자의 견해로는 Novell이 만든 가장 안정적인 버전입니다. AppDomain 언로드 (segfaults)에 문제가 있지만 매우 드물게 실패하며 이것은 우리가 받아 들일 수 있습니다.

괜찮아. 그러나 .net 4.0의 기능을 사용하려면 버전 2.10.x 또는 3.x로 전환해야하며 여기서 문제가 시작됩니다.

2.6.7과 비교하여 새 버전은 사용할 수 없습니다. 모노 설치를 테스트하는 간단한 스트레스 테스트 응용 프로그램을 작성했습니다.

사용 지침과 함께 여기에 있습니다 : https://github.com/head-thrash/stress_test_mono

스레드 풀 작업자 스레드를 사용합니다. Worker는 dll을 AppDomain에로드하고 수학 작업을 시도합니다. 일부 작업은 스레드가 많고 일부는 단일 작업입니다. 디스크에서 일부 파일 읽기가 있지만 거의 모든 작업이 CPU에 종속됩니다.

결과가 좋지 않습니다. 실제로 버전 3.0.12의 경우 :

  • sgen GC segfaults 프로세스가 거의 즉시
  • boehm을 가진 모노는 더 오래 (2-5 시간) 살지만 segfaults는 결국

위에서 언급했듯이 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 논리에 연결되어 있으므로 모노에서 멀리 떨어져 있어야합니다.

BTW, 테스트 된 프로그램은 MS .NET 4.5 env의 Windows 컴퓨터에서 24 시간 동안 아무런 문제없이 작동했습니다.

결론적으로 모노를 조심스럽게 사용하십시오. 언뜻보기에 작동하지만 언제든지 쉽게 실패 할 수 있습니다. 오픈 소스 프로젝트에서 많은 핵심 덤프와 주요 믿음 상실을 경험하게 될 것입니다.