Domanda

Qualcuno ha utilizzato Mono, l'implementazione .NET open source su un progetto di grandi o medie dimensioni?Mi chiedo se sia pronto per il mondo reale, gli ambienti di produzione.È stabile, veloce, compatibile, ...abbastanza da usare?Ci vuole molto impegno per trasferire i progetti sul runtime Mono o è davvero così? Veramente sufficientemente compatibile da poter semplicemente prendere ed eseguire codice già scritto per il runtime di Microsoft?

È stato utile?

Soluzione

Ci sono un paio di scenari da considerare:(a) se stai effettuando il porting di un'applicazione esistente e ti chiedi se Mono è abbastanza buono per questo compito;(b) stai iniziando a scrivere del nuovo codice e vuoi sapere se Mono è abbastanza maturo.

Per il primo caso è possibile utilizzare il file Strumento Analizzatore di migrazione mono (Moma) per valutare quanto è lontana la tua applicazione dall'esecuzione su Mono.Se la valutazione viene restituita a pieni voti, dovresti iniziare i test e il QA e prepararti per la spedizione.

Se la tua valutazione ritorna con un report che evidenzia funzionalità mancanti o che differiscono significativamente nella loro semantica in Mono dovrai valutare se il codice può essere adattato, riscritto o nel peggiore dei casi se la tua applicazione può funzionare con funzionalità ridotte.

Secondo le nostre statistiche Moma basate sugli invii degli utenti (questo viene dalla memoria) circa il 50% delle applicazioni funziona immediatamente, circa il 25% richiede circa una settimana di lavoro (refactoring, adattamento) un altro 15% richiede un serio impegno per rifai parti del tuo codice e il resto non vale la pena preoccuparsi del porting poiché sono così incredibilmente legati a Win32.A quel punto, o inizi da zero, oppure una decisione aziendale guiderà lo sforzo per rendere il tuo codice portabile, ma stiamo parlando di mesi di lavoro (almeno dai rapporti che abbiamo).

Se inizi da zero, la situazione è molto più semplice, perché utilizzerai solo le API presenti in Mono.Finché rimani con lo stack supportato (che è praticamente .NET 2.0, più tutti gli aggiornamenti principali in 3.5 inclusi LINQ e System.Core, più qualsiasi API multipiattaforma Mono) starai bene.

Di tanto in tanto potresti imbatterti in bug in Mono o limitazioni e potresti dover aggirarli, ma questo non è diverso da qualsiasi altro sistema.

Per quanto riguarda la portabilità:Le applicazioni ASP.NET sono quelle più facili da trasferire, poiché hanno poche o nessuna dipendenza da Win32 e puoi persino utilizzare SQL Server o altri database popolari (ci sono molti provider di database in bundle con Mono).

Il porting di Windows.Forms è talvolta più complicato perché agli sviluppatori piace sfuggire alla sandbox .NET e fare P/Invoke per configurare cose utili come la modifica della velocità di lampeggiamento del cursore espressa come due punti Bezier codificati in formato BCD in un wParam.O qualche spazzatura del genere.

Altri suggerimenti

Ha una copertura piuttosto ampia fino a .NET 4.0 e include anche alcune funzionalità delle API .NET 4.5, ma ci sono alcune aree che abbiamo scelto di non implementare a causa della deprecazione delle API, della creazione di nuove alternative o dell'ambito troppo ampio grande.Le seguenti API non sono disponibili in Mono:

  • Fondazione presentazione Windows
  • Windows Workflow Foundation (nessuna delle due versioni)
  • Struttura delle entità
  • I "componenti aggiuntivi" WSE1/WSE2 allo stack dei servizi Web standard

Inoltre, la nostra implementazione WCF è limitata a quanto supportato da Silverlight.

Il modo più semplice per verificare il tuo progetto specifico è eseguire il file Analizzatore di mono migrazione (MoMA).Il vantaggio è che notificherà al team di Mono i problemi che ti impediranno di utilizzare Mono (se presente), consentendo loro di dare priorità al proprio lavoro.

Recentemente ho eseguito MoMA su SubSonic e ho riscontrato un solo problema: uno strano uso dei tipi Nullable.È una grande base di codice, quindi la copertura è stata piuttosto impressionante.

Mono è in uso attivo in diversi prodotti commerciali e open source.È in uso in alcune applicazioni di grandi dimensioni, come Wikipedia e il Centro sviluppatori Mozilla, ed è stato utilizzato in applicazioni integrate come i lettori MP3 Sansa e alimenta migliaia di giochi pubblicati.

A livello linguistico, il compilatore Mono è completamente compatibile con la specifica del linguaggio C# 5,0.

Sul lato desktop, Mono funziona alla grande se ti impegni a utilizzare GTK#.L'implementazione di Windows.Forms è ancora un po' difettosa (ad esempio, TrayIcon non funziona) ma ha fatto molta strada.Inoltre, GTK# è un toolkit migliore di Windows Form così com'è.

Sul lato web, Mono ha implementato abbastanza ASP.NET per eseguire perfettamente la maggior parte dei siti.La difficoltà qui è trovare un host su cui è installato mod_mono su apache o farlo da soli se si dispone dell'accesso shell al proprio host.

In ogni caso, Mono è fantastico e stabile.

Cose fondamentali da ricordare quando si crea un programma multipiattaforma:

  • Utilizza GTK# invece di Windows.Forms
  • Assicurati di scrivere correttamente i nomi dei file
  • Utilizzo Path.Separator invece di hardcoding "\", utilizzare anche Environment.NewLine invece di "\n".
  • Non utilizzare chiamate P/Invoked all'API Win32.
  • Non utilizzare il registro di Windows.

Personalmente utilizzo Mono in un ambiente di prima serata.Utilizzo server mono che si occupano di gigabyte di attività relative all'elaborazione dei dati udp/tcp e non potrei essere più felice.

Ci sono delle peculiarità e una delle cose più fastidiose è che non puoi semplicemente "costruire" i tuoi file msbuild a causa dello stato attuale di Mono:

  • MonoDevelop (l'IDE) ha un supporto parziale per msbuild, ma sostanzialmente funzionerà su qualsiasi configurazione di build "REAL" oltre un semplice hello-world (attività di build personalizzate, "proprietà" dinamiche come $(SolutionDir), configurazione reale per citarne alcuni morti -finisce)
  • xbuild quale Avrebbe dovuto essere il sistema di build mono-fornito-msbuild-completamente compatibile è ancora più orribile, quindi costruire dalla riga di comando è in realtà un'esperienza peggiore rispetto all'utilizzo della GUI, che è uno stato dell'unione molto "non ortodosso" per gli ambienti Linux. ..

Una volta/durante la realizzazione delle tue cose, potresti vedere alcune lacune anche per il codice che DOVREBBE essere supportato come:

  • il compilatore si stanca di determinati costrutti
  • e alcune classi .NET più avanzate/nuove che ti lanciano schifezze inaspettate (XLinq qualcuno?)
  • alcune "funzionalità" di runtime immature (limite heap di 3 GB su x64...WTF!)

ma ha detto che in generale le cose iniziano a funzionare molto rapidamente e le soluzioni/soluzioni alternative sono abbondanti.

Una volta superati gli ostacoli iniziali, la mia esperienza è che il mono ROCKS e continua a migliorare ad ogni iterazione.

Ho avuto server in esecuzione in mono, che elaboravano 300 GB di dati al giorno, con tonnellate di p/invoke e in generale facendo MOLTO lavoro e rimanendo ATTIVO per 5-6 mesi, anche con il mono "bleeding edge".

Spero che questo ti aiuti.

Le raccomandazioni per la risposta accettata sono un po' obsolete ora.

  • L'implementazione dei moduli Windows è abbastanza buona ora.(Vedere Vernice-Mono per un port di Paint.net che è un'applicazione Windows Form piuttosto complessa.Tutto ciò che era richiesto era un livello di emulazione per alcuni P-Invoke e chiamate di sistema non supportate).
  • Path.Combine e Path.Seperator per unire percorsi e nomi di file.
  • Il registro di Windows va bene, purché lo utilizzi solo per archiviare e recuperare dati dalle tue applicazioni (ad es.non è possibile ottenere alcuna informazione su Windows da esso, poiché è fondamentalmente un registro per le applicazioni Mono).

Se vuoi usare WPF sei sfortunato. Mono attualmente non ha intenzione di implementarlo.

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

Bene, il mono è fantastico, ma per quanto posso vedere è instabile.Funziona, ma si guasta quando si affida al processo mono un lavoro serio da svolgere.

TL;DR - Non utilizzare mono se:

  • utilizzare AppDomain (Assembly Load\Unload) in ambienti multithread
  • Non è possibile sostenere il modello "lascia fallire".
  • Si verificano eventi occasionali di carico pesante durante l'esecuzione del processo

Quindi, i fatti.

Usiamo mono-2.6.7 (.net v 3.5) su RHEL5, Ubuntu e, dal mio punto di vista, è la versione più stabile creata da Novell.Ha un problema con lo scaricamento degli AppDomain (segfaults), tuttavia, fallisce molto raramente e questo, di gran lunga, è accettabile (da noi).

Va bene.Ma se vuoi utilizzare le funzionalità di .net 4.0, devi passare alle versioni 2.10.xo 3.x, ed è qui che iniziano i problemi.

Rispetto alla 2.6.7, le nuove versioni sono semplicemente inaccettabili da utilizzare.Ho scritto una semplice applicazione di stress test per testare le installazioni mono.

È qui, con le istruzioni per l'uso: https://github.com/head-thrash/stress_test_mono

Utilizza thread di lavoro del pool di thread.Il lavoratore carica la DLL su AppDomain e tenta di eseguire alcuni calcoli.Alcuni lavori sono multi-thread, altri sono singoli.Quasi tutto il lavoro è legato alla CPU, sebbene siano presenti alcune letture di file dal disco.

I risultati non sono molto buoni.Infatti per la versione 3.0.12:

  • I segfault di sgen GC vengono elaborati quasi immediatamente
  • mono con boehm dura più a lungo (da 2 a 5 ore), ma prima o poi si guasta

Come accennato in precedenza, sgen gc semplicemente non funziona (mono creato dal sorgente):

* 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]

Per quanto riguarda boehm segfauls, ad esempio (Ubuntu 13.04, mono costruito dal sorgente):

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

Oppure (RHEL5, mono è tratto da RPM qui 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

Entrambi gli errori sono in qualche modo collegati alla logica di AppDomains, quindi dovresti starne lontano in mono.

A proposito, il programma testato ha funzionato 24 ore su computer Windows in MS .NET 4.5 env senza alcun errore.

Quindi, in conclusione, vorrei dire: usate mono con cautela.Funziona a prima vista, ma può facilmente fallire in qualsiasi momento.Rimarresti con un mucchio di core dump e una grave perdita di fiducia nei progetti opensource.

Il MoMA è un ottimo strumento per questo, come ha suggerito qualcun altro.Le maggiori fonti di incompatibilità al giorno d'oggi sono le applicazioni che DllImport (o P/Invoke) nelle librerie Win32.Alcuni assembly non sono implementati, ma la maggior parte di essi è solo per Windows e non avrebbe senso su Linux.Penso che sia abbastanza sicuro affermare che la maggior parte delle applicazioni ASP.NET può essere eseguita su Mono con modifiche limitate.

(Divulgazione:Ho contribuito allo stesso Mono e alle app scritte che vengono eseguite su di esso.)

In molti casi è possibile prendere il codice esistente ed eseguirlo semplicemente su Mono, in particolare se si esegue il porting di un'applicazione ASP.NET.

In alcuni casi, potresti aver bisogno di sezioni di codice completamente nuove per farlo funzionare.Se utilizzi System.Windows.Forms, ad esempio, l'applicazione non funzionerà senza modifiche.Allo stesso modo se utilizzi un codice specifico di Windows (codice di accesso al registro, ad esempio).Ma penso che il peggior trasgressore sia il codice dell'interfaccia utente.Ciò è particolarmente negativo sui sistemi Macintosh.

Lo abbiamo utilizzato per un progetto qui al lavoro che doveva essere eseguito su Linux ma riutilizzavamo alcune librerie .NET che abbiamo creato in Managed C++.Sono rimasto molto sorpreso da come ha funzionato bene.Il nostro eseguibile principale è scritto in C# e possiamo semplicemente fare riferimento ai nostri binari C++ gestiti senza problemi.L'unica differenza nel codice C# tra Windows e Linux è il codice della porta seriale RS232.

L'unico grosso problema a cui riesco a pensare è successo circa un mese fa.La build Linux presentava una perdita di memoria che non era stata riscontrata nella build Windows.Dopo aver eseguito un po' di debug manuale (i profiler di base per Mono su Linux non sono stati di grande aiuto), siamo riusciti a restringere il problema a una specifica porzione di codice.Alla fine abbiamo trovato una soluzione alternativa, ma ho ancora bisogno di trovare un po' di tempo per tornare indietro e capire quale fosse la causa principale della perdita.

Sapete quanto è valido il supporto dell'anteprima di Mono 2.0 per Windows Forms 2.0?

Dal poco che ci ho giocato, mi è sembrato relativamente completo e quasi utilizzabile.Semplicemente non sembrava proprio giusto in alcuni punti ed è ancora un po' incostante nel complesso.Mi ha stupito che abbia funzionato così bene con alcuni dei nostri moduli, anche se onestamente.

Sì, sicuramente lo è (se stai attento però) supportiamo mono in ra-ajax (biblioteca Ajax trovata a http://ra-ajax.org) e nella maggior parte dei casi non abbiamo alcun problema.Devi stare attento con alcune delle "cose ​​più folli" di .Net come WSE ecc., e probabilmente anche alcuni dei tuoi progetti esistenti non saranno compatibili al 100% con Mono, ma i nuovi progetti se li testerai durante lo sviluppo lo faranno per lo più essere compatibile senza problemi con Mono.E il guadagno derivante dal supporto di Linux ecc. attraverso l'utilizzo di Mono è davvero interessante ;)

Penso che gran parte del segreto del supporto di Mono sia utilizzare gli strumenti giusti fin dall'inizio, ad es.ActiveRecord, log4net, ra-ajax ecc...

Per il tipo di applicazione che stiamo realizzando Mono purtroppo non sembra pronto per la produzione.Nel complesso ne siamo rimasti impressionati e impressionati dalle sue prestazioni sia su Windows che su macchine EC2, tuttavia, il nostro programma si bloccava costantemente con errori di garbage collection sia su Windows che su Linux.

Il messaggio di errore è:"Errori fatali in GC:troppe sezioni heap", ecco un collegamento a qualcun altro che ha riscontrato il problema in un modo leggermente diverso:

http://bugzilla.novell.com/show_bug.cgi?id=435906

Il primo pezzo di codice che abbiamo eseguito in Mono era una semplice sfida di programmazione che avevamo sviluppato...Il codice carica circa 10 MB di dati in alcune strutture dati (ad es.HashSets), quindi esegue 10 query sui dati.Abbiamo eseguito le query 100 volte per cronometrarle e ottenere una media.

Il codice si è bloccato intorno alla 55a query su Windows.Su Linux funzionava, ma non appena passavamo a un set di dati più grande, anche lui si bloccava.

Questo codice è molto semplice, ad es.inserisci alcuni dati in HashSet e quindi esegui query su tali HashSet ecc., tutto C# nativo, niente di pericoloso, nessuna chiamata API.Su Microsoft CLR non si blocca mai e funziona su enormi set di dati migliaia di volte senza problemi.

Uno dei nostri ragazzi ha inviato un'e-mail a Miguel includendo il codice che ha causato il problema, ancora nessuna risposta.:(

Sembra anche che molte altre persone abbiano riscontrato questo problema senza soluzione: è stata suggerita una soluzione per ricompilare Mono con impostazioni GC diverse, ma ciò sembra semplicemente aumentare la soglia prima della quale si blocca.

Basta controllare www.plasticscm.com.Tutto (client, server, GUI, strumenti di unione) è scritto su mono.

Dipende davvero dagli spazi dei nomi e dalle classi che stai utilizzando dal framework .NET.Ero interessato a convertire uno dei miei servizi Windows in modo che potesse essere eseguito sul mio server di posta elettronica, ovvero Suse, ma ci siamo imbattuti in diversi ostacoli con API che non erano state completamente implementate.C'è una tabella da qualche parte sul sito web di Mono che elenca tutte le lezioni e il loro livello di completamento.Se la tua richiesta è coperta, accettala.

Come qualsiasi altra applicazione, ovviamente, esegui la prototipazione e i test prima di impegnarti completamente.

Un altro problema che abbiamo riscontrato riguarda il software con licenza:se fai riferimento alla DLL di qualcun altro, non puoi codificare le incompatibilità sepolte in quell'assembly.

Immagino quindi che se hai un'applicazione con alcuni componenti di terze parti potresti essere pieno.Dubito che molti fornitori svilupperanno pensando a Mono

Esempio: http://community.devexpress.com/forums/p/55085/185853.aspx

No, mono non è pronto per un lavoro serio.Ho scritto alcuni programmi su Windows utilizzando F# e li ho eseguiti su Mono.Questi programmi utilizzavano disco, memoria e CPU in modo piuttosto intensivo.Ho riscontrato arresti anomali nelle librerie mono (codice gestito), arresti anomali nel codice nativo e arresti anomali nella macchina virtuale.Quando mono funzionava, i programmi erano almeno due volte più lenti rispetto a .Net in Windows e utilizzavano molta più memoria.Stai lontano dalla mononucleosi per lavori seri.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top