Mono はゴールデンタイムに向けて準備ができていますか?[閉まっている]

StackOverflow https://stackoverflow.com/questions/18450

  •  09-06-2019
  •  | 
  •  

質問

大規模または中規模のプロジェクトでオープンソースの .NET 実装である Mono を使用した人はいますか?実世界の運用環境に対応できるかどうか疑問に思っています。安定しているか、速いか、互換性があるか...使用するのに十分ですか?プロジェクトを Mono ランタイムに移植するには多大な労力が必要ですか、それとも本当にそうでしょうか? 本当に Microsoft のランタイム用に既に書かれたコードをそのまま取得して実行するのに十分な互換性があるでしょうか?

役に立ちましたか?

解決

考慮すべきシナリオがいくつかあります。(a) 既存のアプリケーションを移植していて、このタスクに Mono が十分かどうか疑問に思っている場合。(b) 新しいコードを書き始めており、Mono が十分に成熟しているかどうかを知りたいと考えています。

最初のケースでは、 Mono 移行アナライザー ツール (Moma) を使用して、アプリケーションが Mono での実行からどの程度離れているかを評価します。評価が見事に返された場合は、テストと QA を開始し、出荷の準備をする必要があります。

評価結果から、Mono で不足している機能やセマンティクスが大きく異なる機能を強調するレポートが返された場合は、コードを適応させたり、書き換えたりできるかどうか、あるいは最悪の場合、アプリケーションが制限された機能で動作できるかどうかを評価する必要があります。

ユーザーの投稿に基づいた Moma の統計 (これは記憶によるものです) によると、アプリケーションの約 50% はすぐに動作し、約 25% は約 1 週間相当の作業 (リファクタリング、適応) を必要とし、さらに 15% は真剣な取り組みが必要です。コードの一部をやり直してください。残りの部分は Win32 に信じられないほど結びついているため、わざわざ移植する価値はありません。その時点で、ゼロから始めるか、ビジネス上の決定によってコードを移植可能にする取り組みが推進されるかのどちらかになりますが、(少なくとも私たちが入手したレポートによると) 数か月に相当する作業が必要になります。

最初から始める場合は、Mono に存在する API のみを使用するため、状況ははるかに単純になります。サポートされているスタック (ほとんど .NET 2.0 に加え、LINQ と System.Core を含む 3.5 のすべてのコア アップグレード、および Mono クロスプラットフォーム API のいずれか) を使用している限り、問題はありません。

場合によっては、Mono のバグや制限に遭遇し、それらを回避する必要があるかもしれませんが、それは他のシステムと変わりません。

携帯性に関しては:ASP.NET アプリケーションは、Win32 への依存関係がほとんどまたはまったくなく、SQL サーバーやその他の一般的なデータベースも使用できるため、移植が簡単です (Mono にはバンドルされたデータベース プロバイダーが多数あります)。

Windows.Forms の移植は、開発者が .NET サンドボックスを脱出し、wParam の BCD 形式でエンコードされた 2 つのベジェ点として表現されるカーソルの点滅速度の変更などの便利な設定を行うために頭を働かせることを好むため、場合によってはトリッキーになります。あるいはそのようなジャンク品。

他のヒント

.NET 4.0 までをかなり広範囲にカバーしており、.NET 4.5 API のいくつかの機能も含まれていますが、API が非推奨になったり、新しい代替手段が作成されたり、スコープが狭すぎたりするため、実装しないことを選択した領域がいくつかあります。大きい。次の API は Mono では使用できません。

  • Windows プレゼンテーション財団
  • Windows Workflow Foundation (2 つのバージョンのどちらでもない)
  • エンティティフレームワーク
  • 標準 Web サービス スタックへの WSE1/WSE2「アドオン」

さらに、WCF 実装は Silverlight がサポートするものに限定されます。

特定のプロジェクトを確認する最も簡単な方法は、 モノ移行アナライザー (MoMA). 。利点は、Mono の使用を妨げる問題 (存在する場合) を Mono チームに通知し、作業に優先順位を付けることができることです。

最近、SubSonic で MoMA を実行しましたが、Nullable 型の奇妙な使用法という問題が 1 つだけ見つかりました。これは大規模なコードベースなので、その範囲はかなり印象的でした。

Mono は以下の分野で積極的に使用されています。 いくつかの商用製品およびオープンソース製品. 。次のようないくつかの大規模なアプリケーションで使用されています。 ウィキペディアと Mozilla 開発者センター, 、Sansa MP3 プレーヤーなどの組み込みアプリケーションで使用され、公開されている何千ものゲームに電力を供給しています。

言語レベルでは、 Mono コンパイラは C# 5.0 言語仕様に完全に準拠しています.

デスクトップ側では、GTK# を使用することに専念している場合、Mono はうまく機能します。Windows.Forms の実装にはまだ少しバグがあります (たとえば、TrayIcon が機能しません) が、大きな進歩を遂げています。さらに、GTK# はそのままでは Windows フォームよりも優れたツールキットです。

Web 側では、Mono はほとんどのサイトを完璧に実行するのに十分な ASP.NET を実装しています。ここでの困難は、Apache に mod_mono がインストールされているホストを見つけるか、ホストへのシェル アクセス権がある場合は自分で行うことです。

いずれにせよ、Mono は素晴らしく、安定しています。

クロスプラットフォーム プログラムを作成するときに覚えておくべき重要な点:

  • Windows.Forms の代わりに GTK# を使用する
  • ファイル名の大文字と小文字を適切に区別してください
  • 使用 Path.Separator ハードコーディングの代わりに "\", 、も使用します Environment.NewLine の代わりに "\n".
  • Win32 API への P/Invoked 呼び出しは使用しないでください。
  • Windows レジストリは使用しないでください。

私は個人的にゴールデンタイム環境で Mono を使用しています。私はギガバイトの udp/tcp データ処理関連タスクを処理する Mono サーバーを実行していますが、これ以上に幸せなことはありません。

いくつかの特徴があり、最も厄介なことの 1 つは、Mono の現在の状態のために msbuild ファイルを単純に「ビルド」できないことです。

  • MonoDevelop (IDE) は部分的な msbuild サポートを備えていますが、基本的には単純な hello-world (カスタム ビルド タスク、$(SolutionDir) のような動的な「プロパティ」、実際の構成など) を超えた「実際の」ビルド設定で動作します。 -終了)
  • xbuildどれ になるはずだった mono-supplied-msbuild-full-compatibility-build-system はさらにひどいので、コマンド ラインからのビルドは実際には GUI を使用するよりもひどいエクスペリエンスであり、これは Linux 環境にとって非常に「型破りな」状態です。 ..

実際にビルドすると、次のようなコードがサポートされるべきであるにもかかわらず、荒野がいくつか見られるかもしれません。

  • コンパイラが特定の構造で停止する
  • そして、特定のより高度な/新しい .NET クラスが予期せぬクソを投げてくる (XLinq は誰ですか?)
  • いくつかの未熟なランタイム「機能」(x64 での 3GB ヒープ制限...なんと!)

しかし、一般的に物事は非常に早く機能し始め、解決策や回避策は豊富にあるとも述べています。.

最初のハードルを乗り越えると、私の経験ではモノラルがロックになり、反復するたびに良くなっています。.

私は Mono でサーバーを実行しており、1 日あたり 300 GB のデータを処理し、大量の p/invoke を実行し、一般的に言えば、「最先端」の Mono であっても、大量の作業を実行し、5 ~ 6 か月間稼動し続けました。

お役に立てれば。

受け入れられた回答の推奨事項は、現在では少し古くなっています。

  • Windows フォームの実装はかなり良くなりました。(見る ペイントモノ かなり複雑な Windows フォーム アプリケーションである Paint.net のポート用です。必要なのは、一部の P-Invoke およびサポートされていないシステム コール用のエミュレーション層だけでした)。
  • Path.Combine と Path.Seperator を使用してパスとファイル名を結合します。
  • Windows レジストリは、アプリケーションのデータの保存と取得にのみ使用している限りは問題ありません (例:これは基本的に Mono アプリケーションのレジストリであるため、そこから Windows に関する情報を取得することはできません)。

WPF を使用したい場合は、運が悪いです。Mono には現在、WPF を実装する予定はありません。

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

まあ、monoは素晴らしいですが、私が見る限り、それは不安定です。それは機能しますが、mono プロセスに重大な作業をさせると失敗します。

TL;DR - 次の場合はモノラルを使用しないでください。

  • マルチスレッド環境で AppDomains (アセンブリのロード/アンロード) を使用する
  • 「失敗しても構わない」モデルを維持できない
  • プロセス実行中に時折高負荷イベントが発生する

それで、事実。

私たちは RHEL5、Ubuntu で mono-2.6.7 (.net v 3.5) を使用していますが、私の見解では、これが Novell によって構築された最も安定したバージョンです。AppDomain のアンロード (セグメンテーション違反) に関する問題がありますが、失敗することは非常にまれであり、これは (当社では) 許容範囲内です。

わかった。しかし、.net 4.0 の機能を使用したい場合は、バージョン 2.10.x または 3.x に切り替える必要があり、そこから問題が始まります。

2.6.7 と比較すると、新しいバージョンは使用できません。モノラル インストールをテストするための簡単なストレス テスト アプリケーションを作成しました。

使用手順はここにあります: https://github.com/head-thrash/stress_test_mono

スレッド プール ワーカー スレッドを使用します。ワーカーは DLL を AppDomain にロードし、いくつかの計算作業を実行しようとします。作業の中にはマルチスレッドのものもあれば、シングルスレッドのものもあります。ディスクからのファイルの読み取りもいくつかありますが、ほとんどすべての作業は CPU に依存します。

結果はあまり良くありません。実際、バージョン 3.0.12 の場合:

  • sgen GC セグメンテーション違反はほぼ即時に処理されます
  • boehm を使用したモノラルはより長く存続します (2 時間から 5 時間) が、最終的にはセグメンテーション違反になります。

上で述べたように、sgen gc は動作しません (mono はソースからビルドされています)。

* 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 ロジックに関連しているため、mono ではこれらの障害に近づかないようにする必要があります。

ところで、テストされたプログラムは、MS .NET 4.5 環境の Windows マシン上で 24 時間問題なく動作しました。

結論として、mono の使用には注意してください。一見したところうまくいきますが、いつでも簡単に失敗する可能性があります。大量のコアダンプと、オープンソースプロジェクトに対する大きな信頼の喪失が残ることになるでしょう。

他の人が示唆したように、MoMA はこれに最適なツールです。最近の非互換性の最大の原因は、Win32 ライブラリに DllImport (または P/Invoke) を行うアプリケーションです。一部のアセンブリは実装されていませんが、そのほとんどは Windows 専用であり、Linux では実際には意味がありません。ほとんどの ASP.NET アプリケーションは、限られた変更を加えれば Mono 上で実行できると言っても過言ではないと思います。

(開示:私は Mono 自体に貢献しただけでなく、Mono 上で実行されるアプリを作成しました。)

多くの場合、特に ASP.NET アプリケーションを移植する場合は、既存のコードをそのまま Mono で実行できます。

場合によっては、それを機能させるためにコードのまったく新しいセクションが必要になることがあります。たとえば、System.Windows.Forms を使用する場合、アプリケーションはそのままでは動作しません。Windows 固有のコード (レジストリ アクセス コードなど) を使用する場合も同様です。しかし、最も悪いのは UI コードだと思います。これは、Macintosh システムでは特に問題です。

私たちはこれを、Linux 上で実行する必要がある職場のプロジェクトに使用してきましたが、マネージド C++ で構築したいくつかの .NET ライブラリを再利用しました。それがどれほどうまくいったかに非常に驚いています。メインの実行可能ファイルは C# で書かれており、マネージド C++ バイナリを問題なく参照することができます。Windows と Linux の C# コードの唯一の違いは、RS232 シリアル ポート コードです。

私が思いつく唯一の大きな問題は、約 1 か月前に起こりました。Linux ビルドには、Windows ビルドでは見られなかったメモリ リークが発生しました。手動でデバッグを行った後 (Linux 上の Mono の基本プロファイラーはあまり役に立ちませんでした)、問題をコードの特定の部分に絞り込むことができました。最終的には回避策のパッチを適用しましたが、時間を見つけて遡って漏れの根本原因を突き止める必要があります。

Mono 2.0 プレビューの Windows Forms 2.0 サポートがどれほど優れているかご存知ですか?

少し遊んだ限りでは、比較的完成度が高く、ほぼ使えるように見えました。いくつかの場所で完全に適切に見えなかっただけで、全体的にはまだ少し当たり外れがあります。正直なところ、それがいくつかのフォームと同じように機能したことに驚きました。

ああ、確かにそうだ(気をつけていればね)。 私たちは、Ra-Ajax (以下にあるAjaxライブラリ)でMonoをサポートしています。 http://ra-ajax.org)そしてほとんど問題はありません。WSE などの .Net の「最も非常識なもの」のいくつかには注意する必要があります。また、おそらく既存のプロジェクトのかなりの数は 100% Mono 互換ではありませんが、開発中にテストすると、新しいプロジェクトはほとんどの場合、Mono 互換になります。 Monoと問題なく互換性があります。そして、Mono を使用することで Linux などをサポートすることで得られるメリットは本当に素晴らしいものです ;)

Mono をサポートする秘訣の大部分は、最初から適切なツールを使用することだと思います。ActiveRecord、log4net、ra-ajax など...

私たちが構築している種類のアプリケーションでは、残念ながら Mono は運用の準備ができていないようです。私たちは全体的にこのプログラムに感銘を受け、Windows と EC2 マシンの両方でのパフォーマンスに感銘を受けましたが、Windows と Linux の両方でプログラムがガベージ コレクション エラーで一貫してクラッシュしました。

エラーメッセージは次のとおりです。「GC での致命的なエラー:ヒープ セクションが多すぎます」という場合は、少し異なる方法で問題を経験している他の人へのリンクを次に示します。

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

Mono で実行した最初のコードは、私たちが開発した単純なプログラミングの課題でした。このコードは、約 10MB のデータをいくつかのデータ構造にロードします (例:HashSets) を使用して、データに対して 10 個のクエリを実行します。時間を測定して平均を取得するために、クエリを 100 回実行しました。

Windows では、55 番目のクエリのあたりでコードがクラッシュしました。Linux では機能しましたが、より大きなデータセットに移動するとすぐにクラッシュしてしまいます。

このコードは非常に単純です。データを HashSet に入れて、それらの HashSet などをクエリします。すべてネイティブ C# で、安全でないものは何もなく、API 呼び出しもありません。Microsoft CLR ではクラッシュすることはなく、巨大なデータ セットを何千回も問題なく実行できます。

私たちの担当者の一人がミゲルに電子メールを送り、問題の原因となったコードを添付しましたが、まだ返答はありません。:(

また、他の多くの人が解決策のないこの問題に遭遇しているようです。解決策の 1 つは、Mono を異なる GC 設定で再コンパイルすることを提案されていますが、それはクラッシュするまでのしきい値が増加するだけのようです。

www.プラスチックcm.comをチェックしてください。すべて (クライアント、サーバー、GUI、マージ ツール) は mono で書かれています。

実際には、.NET Framework から使用している名前空間とクラスに依存します。Windows サービスの 1 つである Suse を電子メール サーバーで実行できるように変換することに興味がありましたが、完全に実装されていない API によっていくつかの大きな障害に遭遇しました。Mono の Web サイトのどこかに、すべてのクラスとその完了レベルをリストした表があります。あなたのアプリケーションがカバーされている場合は、それを試してください。

もちろん、他のアプリケーションと同様に、本格的に取り組む前にプロトタイピングとテストを行ってください。

私たちが遭遇したもう 1 つの問題は、ライセンスを取得したソフトウェアです。他の人の DLL を参照している場合、そのアセンブリに埋もれている非互換性を回避するコードを作成することはできません。

サードパーティのコンポーネントを含むアプリケーションがある場合、詰まる可能性があると思います。多くのベンダーが Mono を念頭に置いて開発するとは思えません

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

いいえ、mono は本格的な作業を行う準備ができていません。Windows 上で F# を使用していくつかのプログラムを作成し、Mono 上で実行しました。これらのプログラムはディスク、メモリ、CPU を非常に集中的に使用しました。モノラル ライブラリ (マネージド コード) でのクラッシュ、ネイティブ コードでのクラッシュ、仮想マシンでのクラッシュが確認されました。Mono が動作したとき、プログラムは Windows の .Net よりも少なくとも 2 倍遅く、より多くのメモリを使用しました。本格的な作業の場合はモノラルから離れてください。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top