Pergunta

Alguém já usou o Mono, a implementação do .NET de código aberto em um projeto de grande ou médio porte?Estou me perguntando se ele está pronto para ambientes de produção do mundo real.É estável, rápido, compatível, ...o suficiente para usar?É preciso muito esforço para portar projetos para o tempo de execução Mono ou é realmente realmente compatível o suficiente para apenas retirar e executar código já escrito para o tempo de execução da Microsoft?

Foi útil?

Solução

Existem alguns cenários a serem considerados:(a) se você estiver portando um aplicativo existente e se perguntando se o Mono é bom o suficiente para esta tarefa;(b) você está começando a escrever um novo código e quer saber se o Mono está maduro o suficiente.

Para o primeiro caso, você pode usar o Ferramenta Analisador de Migração Mono (Moma) para avaliar o quão longe seu aplicativo está de rodar no Mono.Se a avaliação voltar com louvor, você deve começar os testes e o controle de qualidade e se preparar para o envio.

Se sua avaliação retornar com um relatório destacando recursos que estão faltando ou diferem significativamente em sua semântica no Mono, você terá que avaliar se o código pode ser adaptado, reescrito ou, na pior das hipóteses, se seu aplicativo pode funcionar com funcionalidade reduzida.

De acordo com nossas estatísticas do Moma baseadas em envios de usuários (isto é de memória), cerca de 50% dos aplicativos funcionam imediatamente, cerca de 25% exigem cerca de uma semana de trabalho (refatoração, adaptação) outros 15% exigem um compromisso sério com refaça partes do seu código, e o resto simplesmente não vale a pena se preocupar em portar, já que eles estão incrivelmente vinculados ao Win32.Nesse ponto, ou você começa do zero ou uma decisão de negócios impulsionará o esforço para tornar seu código portátil, mas estamos falando de meses de trabalho (pelo menos pelos relatórios que temos).

Se você está começando do zero, a situação é bem mais simples, pois você estará utilizando apenas as APIs que estão presentes no Mono.Contanto que você permaneça com a pilha suportada (que é praticamente .NET 2.0, além de todas as atualizações principais do 3.5, incluindo LINQ e System.Core, além de qualquer uma das APIs de plataforma cruzada Mono), você ficará bem.

De vez em quando você pode encontrar bugs ou limitações no Mono e pode ter que contorná-los, mas isso não é diferente de qualquer outro sistema.

Quanto à portabilidade:Os aplicativos ASP.NET são os mais fáceis de portar, pois têm pouca ou nenhuma dependência do Win32 e você pode até usar o SQL Server ou outros bancos de dados populares (há muitos provedores de banco de dados agrupados com Mono).

A portabilidade do Windows.Forms às vezes é mais complicada porque os desenvolvedores gostam de escapar da sandbox .NET e P/Invoke para configurar coisas tão úteis quanto a alteração da taxa de intermitência do cursor expressa como dois pontos bezier codificados no formato BCD em um wParam.Ou algum lixo assim.

Outras dicas

Ele tem uma cobertura bastante extensa até o .NET 4.0 e até inclui alguns recursos das APIs do .NET 4.5, mas há algumas áreas que optamos por não implementar devido às APIs estarem obsoletas, novas alternativas serem criadas ou o escopo ser muito grande.As seguintes APIs não estão disponíveis no Mono:

  • Windows Presentation Foundation
  • Windows Workflow Foundation (nenhuma das duas versões)
  • Estrutura de entidade
  • Os "complementos" WSE1/WSE2 para a pilha padrão de serviços da Web

Além disso, nossa implementação do WCF é limitada ao suporte do Silverlight.

A maneira mais fácil de verificar seu projeto específico é executar o Analisador de Migração Mono (MoMA).A vantagem é que ele notificará a equipe do Mono sobre problemas que impedirão você de usar o Mono (se houver), o que permitirá que eles priorizem seu trabalho.

Recentemente executei o MoMA no SubSonic e encontrei apenas um problema - um uso estranho de tipos Nullable.É uma grande base de código, então a cobertura foi bastante impressionante.

Mono está em uso ativo em vários produtos comerciais e de código aberto.Está em uso em algumas aplicações grandes, como Wikipedia e o Mozilla Developer Center, e tem sido usado em aplicativos incorporados, como os tocadores de MP3 Sansa, e alimenta milhares de jogos publicados.

No nível da linguagem, o compilador Mono é totalmente compatível com a especificação da linguagem C# 5.0.

No lado desktop, o Mono funciona muito bem se você se comprometer a usar o GTK#.A implementação do Windows.Forms ainda apresenta alguns bugs (por exemplo, TrayIcon não funciona), mas já percorreu um longo caminho.Além disso, GTK# é um kit de ferramentas melhor que o Windows Forms.

No lado da web, o Mono implementou ASP.NET suficiente para executar a maioria dos sites perfeitamente.A dificuldade aqui é encontrar um host que tenha o mod_mono instalado no Apache, ou fazer você mesmo se tiver acesso shell ao seu host.

De qualquer forma, o Mono é ótimo e estável.

Pontos importantes a serem lembrados ao criar um programa multiplataforma:

  • Use GTK# em vez de Windows.Forms
  • Certifique-se de definir corretamente seus nomes de arquivos
  • Usar Path.Separator em vez de codificar "\", também use Environment.NewLine em vez de "\n".
  • Não use nenhuma chamada P/Invoked para a API Win32.
  • Não use o Registro do Windows.

Eu pessoalmente uso o Mono em um ambiente de horário nobre.Eu executo servidores mono lidando com gigabytes de tarefas relacionadas ao processamento de dados udp/tcp e não poderia estar mais feliz.

Existem peculiaridades, e uma das coisas mais irritantes é que você não pode simplesmente "construir" seus arquivos msbuild devido ao estado atual do Mono:

  • MonoDevelop (o IDE) tem algum suporte parcial ao msbuild, mas basicamente funciona em qualquer configuração de compilação "REAL" além de um simples hello-world (tarefas de compilação personalizadas, "propriedades" dinâmicas como $(SolutionDir), configuração real, para citar alguns mortos -termina)
  • xbuild qual Deveria ter ficado o sistema de compilação totalmente compatível com msbuild mono-fornecido é ainda mais horrível, então construir a partir da linha de comando é na verdade uma experiência pior do que usar a GUI, que é um estado de união muito "pouco ortodoxo" para ambientes Linux. ..

Uma vez/durante a construção do seu material, você poderá ver algumas situações selvagens, mesmo para códigos que DEVEM ser suportados, como:

  • o compilador sendo prejudicado em certas construções
  • e certas classes .NET mais avançadas/novas jogando porcarias inesperadas em você (alguém XLinq?)
  • alguns "recursos" de tempo de execução imaturos (limite de heap de 3 GB em x64 ...Que merda!)

mas Heaving disse que, de modo geral, as coisas começam a funcionar muito rapidamente e as soluções/soluções alternativas são abundantes.

Depois de superar esses obstáculos iniciais, minha experiência é mono ROCKS e fica cada vez melhor a cada iteração.

Eu tive servidores rodando em mono, processando 300 GB de dados por dia, com toneladas de p/invokes e, de modo geral, fazendo MUITO trabalho e permanecendo ATUAL por 5 a 6 meses, mesmo com o mono "de ponta".

Espero que isto ajude.

As recomendações para a resposta aceita estão um pouco desatualizadas agora.

  • A implementação do Windows Forms está muito boa agora.(Ver Pintura-Mono para uma versão do Paint.net, que é um aplicativo de formulários do Windows bastante complexo.Tudo o que foi necessário foi uma camada de emulação para algumas das chamadas de sistema P-Invoke e não suportadas).
  • Path.Combine e também Path.Seperator para unir caminhos e nomes de arquivos.
  • O registro do Windows está OK, desde que você o use apenas para armazenar e recuperar dados de seus aplicativos (ou seja,você não pode obter nenhuma informação sobre o Windows, pois é basicamente um registro para aplicativos Mono).

Se você quiser usar o WPF, você está sem sorte. Atualmente, o Mono não tem planos de implementá-lo.

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

Bem, mono é ótimo, mas até onde posso ver, é instável.Funciona, mas falha quando você dá ao processo mono um trabalho sério a fazer.

DR - Não use mono se você:

  • use AppDomains (Assembly Load\Unload) em ambientes multithread
  • Não é possível sustentar o modelo “deixar falhar”
  • Experimente eventos ocasionais de carga pesada durante a execução do processo

Então, os fatos.

Usamos mono-2.6.7 (.net v 3.5) no RHEL5, Ubuntu e, no meu ponto de vista, é a versão mais estável construída pela Novell.Ele tem um problema com o descarregamento de AppDomains (segfaults), porém, falha muito raramente e isso, de longe, é aceitável (por nós).

OK.Mas se quiser usar os recursos do .net 4.0, você terá que mudar para as versões 2.10.x ou 3.x, e é aí que os problemas começam.

Em comparação com 2.6.7, novas versões são simplesmente inaceitáveis ​​para uso.Escrevi um aplicativo simples de teste de estresse para testar instalações mono.

Está aqui, com instruções de uso: https://github.com/head-thrash/stress_test_mono

Ele usa threads de trabalho do pool de threads.O trabalhador carrega dll no AppDomain e tenta fazer alguns trabalhos matemáticos.Parte do trabalho é multithread, parte é única.Quase todo o trabalho depende da CPU, embora haja algumas leituras de arquivos do disco.

Os resultados não são muito bons.Na verdade, para a versão 3.0.12:

  • sgen GC segfaults processam quase imediatamente
  • mono com boehm dura mais (de 2 a 5 horas), mas eventualmente falha no seg

Como mencionado acima, sgen gc simplesmente não funciona (mono compilado a partir do código-fonte):

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

Quanto aos segfauls boehm - por exemplo (Ubuntu 13.04, mono construído a partir do código-fonte):

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

Ou (RHEL5, mono é retirado de rpm aqui 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

Ambas as falhas estão de alguma forma conectadas à lógica do AppDomains, portanto, você deve ficar longe delas em mono.

Aliás, o programa testado funcionou 24 horas em uma máquina Windows no ambiente MS .NET 4.5 sem nenhuma falha.

Então, para concluir, gostaria de dizer: use mono com cautela.Funciona à primeira vista, mas pode falhar facilmente a qualquer momento.Você ficaria com um monte de core dumps e grande perda de fé em projetos de código aberto.

O MoMA é uma ótima ferramenta para isso, como alguém sugeriu.As maiores fontes de incompatibilidade atualmente são aplicativos que DllImport (ou P/Invoke) em bibliotecas Win32.Alguns assemblies não são implementados, mas a maioria deles é somente Windows e realmente não faria sentido no Linux.Acho bastante seguro dizer que a maioria dos aplicativos ASP.NET podem ser executados no Mono com modificações limitadas.

(Divulgação:Eu contribuí para o próprio Mono, bem como para aplicativos escritos que rodam sobre ele.)

Em muitos casos, você pode pegar o código existente e executá-lo no Mono, principalmente se estiver portando um aplicativo ASP.NET.

Em alguns casos, você pode precisar de seções de código totalmente novas para que funcione.Se você usar System.Windows.Forms, por exemplo, o aplicativo não funcionará sem modificações.Da mesma forma se você usar algum código específico do Windows (código de acesso ao registro, por exemplo).Mas acho que o pior infrator é o código da IU.Isso é particularmente ruim em sistemas Macintosh.

Estamos usando-o para um projeto aqui no trabalho que precisava ser executado em Linux, mas reutilizamos algumas bibliotecas .NET que construímos em C++ gerenciado.Fiquei muito surpreso com o quão bem tudo funcionou.Nosso executável principal está sendo escrito em C# e podemos apenas referenciar nossos binários C++ gerenciados sem problemas.A única diferença no código C# entre Windows e Linux é o código da porta serial RS232.

O único grande problema em que consigo pensar aconteceu há cerca de um mês.A compilação do Linux teve um vazamento de memória que não foi visto na compilação do Windows.Depois de fazer alguma depuração manual (os criadores de perfil básicos do Mono no Linux não ajudaram muito), conseguimos restringir o problema a um pedaço específico de código.Acabamos corrigindo uma solução alternativa, mas ainda preciso encontrar algum tempo para voltar e descobrir qual foi a causa raiz do vazamento.

Você sabe quão bom é o suporte da visualização do Mono 2.0 para Windows Forms 2.0?

Pelo pouco que brinquei com ele, parecia relativamente completo e quase utilizável.Simplesmente não parecia certo em alguns lugares e ainda é um pouco imprevisível no geral.Fiquei surpreso ao ver que funcionou tão bem quanto com alguns de nossos formulários, embora honestamente.

Sim http://ra-ajax.org) e geralmente não estamos tendo problemas.Você precisa ter cuidado com algumas das "coisas mais insanas" do .Net, como WSE, etc, e também provavelmente alguns de seus projetos existentes não serão 100% compatíveis com Mono, mas novos projetos, se você testá-los durante o desenvolvimento, em sua maioria ser compatível sem problemas com Mono.E o ganho de suportar Linux etc. através do uso do Mono é muito legal;)

Acho que grande parte do segredo do suporte ao Mono é usar as ferramentas certas desde o início, por ex.ActiveRecord, log4net, ra-ajax etc...

Para o tipo de aplicação que estamos construindo, o Mono infelizmente não parece pronto para produção.Ficamos impressionados com ele em geral e com seu desempenho tanto no Windows quanto em máquinas EC2; no entanto, nosso programa travou consistentemente com erros de coleta de lixo no Windows e no Linux.

A mensagem de erro é:"erros fatais no GC:muitas seções de heap", aqui está um link para alguém que está enfrentando o problema de uma maneira um pouco diferente:

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

O primeiro trecho de código que rodamos no Mono foi um simples desafio de programação que desenvolvemos...O código carrega cerca de 10 MB de dados em algumas estruturas de dados (por exemplo,HashSets) e executa 10 consultas nos dados.Executamos as consultas 100 vezes para cronometrar e obter uma média.

O código travou por volta da 55ª consulta no Windows.No Linux funcionou, mas assim que migramos para um conjunto de dados maior, ele também travou.

Este código é muito simples, por ex.coloque alguns dados em HashSets e, em seguida, consulte esses HashSets, etc., todos c # nativos, nada inseguro, sem chamadas de API.No Microsoft CLR, ele nunca trava e funciona perfeitamente em enormes conjuntos de dados milhares de vezes.

Um de nossos funcionários enviou um e-mail para Miguel e incluiu o código que causou o problema, sem resposta ainda.:(

Parece também que muitas outras pessoas encontraram este problema sem solução - uma solução foi sugerida para recompilar o Mono com diferentes configurações de GC, mas isso apenas parece aumentar o limite antes do qual ele trava.

Basta verificar www.plasticscm.com.Tudo (cliente, servidor, GUI, ferramentas de mesclagem) é escrito em mono.

Realmente depende dos namespaces e classes que você está usando no .NET framework.Eu tinha interesse em converter um dos meus serviços do Windows para rodar no meu servidor de e-mail, que é o Suse, mas nos deparamos com vários obstáculos difíceis com APIs que não haviam sido completamente implementadas.Há um gráfico em algum lugar no site do Mono que lista todas as classes e seus níveis de conclusão.Se o seu aplicativo estiver coberto, vá em frente.

Como qualquer outro aplicativo, faça protótipos e testes antes de se comprometer totalmente, é claro.

Outro problema que encontramos é o software licenciado:se você estiver fazendo referência à DLL de outra pessoa, não poderá codificar incompatibilidades ocultas nesse assembly.

Eu imagino então que se você tiver um aplicativo com alguns componentes de terceiros, você pode estar cheio.Duvido que muitos fornecedores desenvolvam com o Mono em mente

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

Não, o mono não está pronto para um trabalho sério.Escrevi alguns programas no Windows usando F# e os executei no Mono.Esses programas usaram disco, memória e CPU de forma bastante intensa.Vi travamentos em bibliotecas mono (código gerenciado), travamentos em código nativo e travamentos na máquina virtual.Quando o mono funcionava, os programas eram pelo menos duas vezes mais lentos do que em .Net no Windows e usavam muito mais memória.Fique longe do mono para trabalhos sérios.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top