japan.internet.com
japan.internet.com メンバーID
Twitter
RSS
  • ニュース
  • コラム
  • リサーチ
  • 特集
  • プレスリリース
  • 専門チャンネル
  • ランキング
  • ホワイトペーパー
  • 価格比較
  • レビュー
  • 資格・スクール
2010年9月9日
デベロッパー2010年3月5日 10:00

生産性向上に役立つMono 2.4のコンポーネントとアーキテクチャ

海外海外internet.com発の記事

はじめに

 MonoはNovellが主導する、ECMA標準に基づく共通言語インフラストラクチャ(Common Language Infrastructure:CLI)のためのオープンソースの.NET開発フレームワークです。Monoプロジェクトは、C#コンパイラや共通言語ランタイム(Common Language Runtime:CLR)など、Linux、BSD、UNIX、Mac OS X、Solaris、Windowsといったプラットフォーム上で動作するLinuxアプリケーションやクロスプラットフォームアプリケーションを開発するための.NET互換のツール群を作成しています(Mono 2.4のアーキテクチャの全体像については図1を参照)。

図1 Mono 2.4のアーキテクチャ:Mono 2.4アーキテクチャの全体像
図1 Mono 2.4のアーキテクチャ:Mono 2.4アーキテクチャの全体像
 Monoの最新バージョンは2.4です(2009年3月30日時点)。

※編集部注1
 この記事の掲載時点(2009年3月30日時点)での最新バージョンは2.4でしたが、現時点では、2009年12月15日にリリースされたMono 2.6が最新となっています。

 このバージョンには.NET FrameworkのコアAPIのほか、Visual Basic .NETとC#バージョン 2.0および(部分的に)3.0のサポートが含まれます。またLINQ to ObjectやLINQ to XMLも配布対象に含まれますが、LINQ to SQLは対象外です。C# 3.0がC#コンパイラのデフォルトの動作モードになり、Windows Forms 2.0もサポートされるようになりました。

 .NET Framework 3.0の実装は「Olive」というMonoの実験的サブプロジェクトで進められていますが、.NET 3.0をサポートしたMonoフレームワークのリリース日はまだ公表されていません(Monoの簡単な歴史についてはこの後の補足説明を参照)。

 この記事では、Windows用のMono 2.4をインストールする方法を説明したうえで、この新バージョンのコンポーネントとアーキテクチャについて解説します。

補足説明1 Monoの歴史
 開発者Miguel de Icaza(Monoプロジェクトの創設者)が.NETテクノロジに興味を持ったのは、2000年12月に.NETのドキュメントが公開されて間もなくのことでした。.NETのバイトコードインタープリタについて調査した彼は、メタデータに関する仕様がないことに気付きました。2001年2月、de IcazaはC#で書かれたC#コンパイラに取り組み始めます。2001年4月、欠落していたファイル形式がECMAによって公開されました。Mono 1.0がリリースされたのは、それから約3年後の2004年6月30日のことです。

 豆知識:Monoのロゴにサルの顔が描かれているのは、monoがスペイン語でサルを意味するからです。

Mono 2.4インストールの概要

 WindowsでMono 2.4を実行するには、次のコンポーネントをインストールする必要があります。

  • Microsoft .NET Framework Version 3.5
  • GTK# for .NETのバージョン2.12.9-2
  • MonoDevelopのバージョン2.1.r136446(図2を参照)
  • Mono Libraries r135450(MonoDevelopをソースからビルドする場合にのみ必要)
 必要なコンポーネントをすべてダウンロードするには、ここをクリックします(図3を参照)。MonoのソースコードはNovellのFTPサイトからダウンロードできます(図4を参照)。

※編集部注2
 上記リンクは最新バージョンへのリンク先となっているため、現時点ではMono Develop 2.2、Mono 2.6がダウンロード可能となっています。

図2 Monoの開発環境:MonoDevelopのグラフィカルエディタのスクリーンショット
図2 Monoの開発環境:MonoDevelopのグラフィカルエディタのスクリーンショット

図3 Windowsプラットフォームに必要なMonoコンポーネントのダウンロードファイル:Windowsで必要となるすべてのMonoコンポーネント
図3 Windowsプラットフォームに必要なMonoコンポーネントのダウンロードファイル:Windowsで必要となるすべてのMonoコンポーネント

図4 Monoソースコードのダウンロード場所: MonoのソースコードはNovellのFTPサイトからダウンロード可能
図4 Monoソースコードのダウンロード場所: MonoのソースコードはNovellのFTPサイトからダウンロード可能
 Monoはいくつかのアーキテクチャで32ビットシステムと64ビットシステムの両方をサポートしており、複数のオペレーティングシステムに対応しています。Monoには、新しいソフトウェアの開発に役立つ次のようなコンポーネントも含まれます。

  • クラスローダ、JIT(Just-In-Time)コンパイラ、ガベージコレクティングランタイムを含む共通言語インフラストラクチャ(CLI)仮想マシン
  • 共通言語ランタイム(CLR)で動作する任意の言語で使用可能なクラスライブラリ(.NET互換のクラスライブラリとMonoが提供するクラスライブラリの双方を含む)
  • C#言語のコンパイラ(将来的に共通言語ランタイムをターゲットとした別のコンパイラがMonoによって開発される可能性あり)
 CLRと共通型システム(Common Type System:CTS)により、バイトコードをターゲットとする何種類もの言語でアプリケーションやライブラリを書くことができます。例えば、代数的な演算を行うクラスの定義をC#で書いておけば、CLIをサポートする他の任意の言語でそのクラスを再利用できます。C#で作成したクラスをC++でサブクラス化し、その結果をEiffelプログラムでインスタンス化することも可能です。こうしたすべての言語で1つのオブジェクトシステム、スレッディングシステム、クラスライブラリ群、ガベージコレクションシステムを共有できます。

 MonoDevelopコンポーネントは、もともとC#をはじめとする.NET言語用に設計された統合開発環境(Integrated Development Environment:IDE)です。MonoDevelopを使えば、開発者はLinux上でデスクトップアプリケーションやASP.NET Webアプリケーションを短時間で書くことができます。また、Visual Studioで作成した.NETアプリケーションをLinuxに移植したり、1つのコードベースですべてのプラットフォームを管理したりすることも容易になります。

 図5に、1つのフォルダにダウンロードされたMono 2.4の全コンポーネントを示します。

図5 ダウンロード後のMonoコンポーネント: Mono 2.4のすべてのコンポーネントが1つのフォルダ内にダウンロードされる
図5 ダウンロード後のMonoコンポーネント: Mono 2.4のすべてのコンポーネントが1つのフォルダ内にダウンロードされる

Mono 2.4のコンポーネント

 Mono 2.4を構成するコンポーネントは、次の3つのグループに分かれます。

  • コアコンポーネント
  • Mono/Linux/GNOME開発スタック
  • Microsoft互換スタック
 コアコンポーネントには、C#コンパイラ、仮想マシン、基底クラスライブラリが含まれます。これらのコンポーネントはEcma-334およびEcma-335規格に基づいているので、Monoは規格に準拠したフリーおよびオープンソースのCLI仮想マシンを提供できます。

 Mono/Linux/GNOME開発スタックは、以下に示すようなGNOMEやフリーおよびオープンソースの既存ライブラリを活用することで、アプリケーション開発用の各種ツールを提供します。

  • GUI開発用のGtk#
  • Geckoレンダリングエンジンを利用するためのMozillaライブラリ
  • UNIX統合ライブラリ
  • データベース接続ライブラリ
  • セキュリティスタック
  • XMLスキーマ言語RelaxNG
 Gtk#を利用すれば、MonoアプリケーションをネイティブアプリケーションとしてGNOMEデスクトップに組み込むことができます。データベース接続ライブラリは、MySQL、SQLite、PostgreSQL、Firebird、Open Database Connectivity(ODBC)、Microsoft SQL Server(MSSQL)、Oracle、オブジェクト関係データベースdb4oなど、多くのデータベースへの接続を可能にします。データベースコンポーネントの開発状況はMonoプロジェクトのWebサイトで公開されています。

 Microsoft互換スタックは、Windows .NETアプリケーションをLinuxに移植する際に使用されます。このグループのコンポーネントには、ADO.NET、ASP.NET、Windows Formsなどが含まれます。これらのコンポーネントはECMA規格ではカバーされておらず、なかにはまだ特許で保護されているものもあります。

C#コンパイラ

 Mono C#コンパイラ(MCS)は、C#のバージョン1.0、2.0、3.0に関しては機能的に完成されたものと見なされています。このコンパイラは、コンパイラそれ自身も含め、多くのC#プログラムをコンパイルできます。約400万行のC#コードから成るMonoや、その他いくつかのプロジェクトのコンパイルでも日常的に使われています。これはかなり高速なコンパイラで、IBM ThinkPad T40の場合、1秒あたり18,000行のC#コードをコンパイルできます。また、Mono.Sharp.dllアセンブリのMono.CSharp.Evaluatorクラスを使用すれば、このコンパイラをサービスとして利用することもできます。Mono 2.6からは、新しいコンパイラであるdmcsがC# 4.0のプレビュー版(C# 4.0の確定前にMono 2.6がリリースされるため)として利用できるようになります。

※編集部注3
 前ページのコメントのとおり、Mono 2.6はリリース済みです。

 C#コンパイラは、定数のたたみ込み(C#言語仕様では必須)やデッドコードの削除など、入力の時点でいくつかの簡単な最適化を実行します。ただし、巻き上げ(hoisting)のような興味深い他の最適化はまだ実行できません。これは、現時点ではコンパイラによる出力時に基本的なブロック演算の実行に適した中間表現が生成されないからです。

 中間層を追加して基本ブロック演算を可能にすることは難しくないはずですが、Monoの開発チームが目指しているのは汎用的なCILオプティマイザです。基本的なブロックベースの最適化を実行するために必要な情報はすべてCILレベルで利用できることから、Monoチームはこのステップを省略し、MCSで生成されたプログラムだけでなく任意のCILプログラムで巻き上げを実行できる汎用のCILオプティマイザを用意していると思われます。

 この汎用CILオプティマイザがさらに拡張されて、定数のたたみ込み(すでにこの機能があるMCSでは不要)やデッドコードの削除が実行可能になれば、他のコンパイラ作成者も自らのプロジェクトでこのツールを使うことで、実稼働用のコンパイラを別途開発せずに済むようになる可能性があります。

Monoランタイム

 Monoランタイムエンジンは、JITコンパイラ、Ahead-of-Time(AOT)コンパイラ、ライブラリローダ、ガベージコレクタ(Boehmによる保守的ガベージコレクタ)、スレッディングシステム、相互運用機能を備えています。Monoランタイムは、スタンドアロンのプロセスとして使用することも、アプリケーションに組み込むこともできます。

 Monoランタイムを組み込めば、既存のCおよびC++コードのすべてを再利用しながらアプリケーションをC#で拡張することができます。

コンパイルエンジン

 JITコンパイラの書き直しによって、これまではなかったいくつかの機能がサポートされるようになりました。その代表例がAOTコンパイル、簡単な移植、コンパイラ最適化のための確固たる基盤などです。AOTコンパイルのねらいは、起動時間短縮のためにネイティブコードへの事前コンパイルを行ったり、実行時にJITコンパイラで使用されるワーキングセットのコンパイルを行ったりすることです。システムにアセンブリ(Mono/.NETの実行可能ファイル)がインストールされていれば、コードを事前にコンパイルしたり、ソフトウェアのインストール先のCPUに合わせてJITコンパイラに生成コードのチューニングを行わせたりすることが可能です。.NETの世界では、こうした作業をngen.exeというツールで行います。

 MonoのAOTコンパイラによって生成されるコードは位置独立コード(Position Independent Code:PIC)なので、普通にJITコンパイルされたコードよりも実行速度が若干遅くなる傾向があります。ただし、パフォーマンスが低下する代わりに、用意されている最適化の手法をすべて使用することができます。

バンドル

 Monoはバンドルにも対応しています。バンドルにより、アプリケーションとそこで使用されるライブラリ、さらにMonoランタイムが1つの実行可能イメージにマージされます。バンドルは、アプリケーション内への「Monoの静的なリンク」と見なせます。

コード最適化のためのプラットフォーム

 Monoチームとしては、Mono VMをJITコンパイラとして使用するだけでなく、Monoによるコード生成をできるだけ効率の高いものにする必要があります。そうした設計には、高、中、低のそれぞれのレベルの中間表現に対して適切に機能する最適化など、さまざまなレベルでの最適化が可能な優れたアーキテクチャが求められます。

 また、それらの最適化のオン/オフを条件によって切り替えられるようにする必要もあります。JITコンパイルでは時間がかかりすぎて使えない最適化でも、AOTコンパイルのときや、プロファイルガイドを併用して実行メソッドのサブセットに対して適用する場合にはオンにできるからです。

ガベージコレクション

 現在、MonoではガベージコレクションエンジンとしてBoehmのガベージコレクタ(GC)を使用しています。その一方で、Mono開発チームはMonoに特化した高精度なコンパクト化GCエンジンにも取り組んでいます。このGCのインターフェイスは、複数のGCエンジンを使用したり特定のタスクに合わせてGCをチューニングしたりできるように分離が進められています。

 このGCは次に示す複数の領域を走査して管理対象オブジェクトへのポインタを探します。

  1. ヒープ(他の管理対象オブジェクトが割り当てられている場所)
    現在、ヒープはほぼ高精度なモードで処理されています。このGCは必ずといっていいほど、ヒープへの参照だけを含むメモリワードだけを考慮するため、ポインタの誤認やその結果としてのメモリリテンションが生じることはほとんどありません。この新しいGCでは、状況を改善するには十分に高精度なモードが必要です。具体的には、参照のビットマップが疎であるようなラージオブジェクトを処理したり、複数のAppDomainを安全に処理したりする必要があります。

  2. スレッドスタックとスレッドレジスタ
    これらは常に保守的に走査されます。この点はMonoの新GCでも(少なくとも、MonoチームがGCの世代移行によって生じたバグを追跡する必要がある初期バージョンでは)変わりません。将来的には、スタックの非管理対象部分だけを保守的に走査するようになるでしょう。

  3. 静的データ領域
    すでにこの部分はBoehm GCと新GCのどちらでも高精度モードで動作するようにMonoチームによって最適化されています。

  4. ランタイムによって割り当てられるデータ構造
    すでにこの部分はおおよそ高精度なモードで動作するようにMonoチームによって最適化されています(つまり、データ構造によって高精度で処理されるものとそうでないものがある)。ただし、特に新しいGCについてはピンドオブジェクトの存在が大きな問題を引き起こす可能性があるため、Monoチームはこの部分に対してさらに取り組む必要があります。

コンパクト化GC(Compacting GC)

 Monoチームは新世代の高精度なコンパクト化GCの開発を進めています。現在、このGCはMonoのSVNリリースから入手できます。この新しいコンパクト化GCは、完全に保守的なGCのいくつかの制限(具体的には、ヒープの断片化によって生じるメモリの消費など)を回避するために実装されました。

 この新しいGCは現在SVNから入手できますが、サポート対象の構成にはなっておらず、Mono 2.4のリリースでもサポート対象の構成にはなっていません。アプリケーションのテストに関心がある開発者や、新しいGCを試したい開発者は利用するとよいでしょう。

 実装の詳細は、Monoの「Compacting GC」(コンパクト化GC)のページに記載されています。

最適化

 JITエンジンには、次のような最適化が実装されています。

  • オペコードのコスト見積り(MonoのアーキテクチャのおかげでMonoチームはさまざまなコードパスをターゲットCPUに応じて動的に生成できる)
  • インライン展開
  • 定数のたたみ込み、コピー伝播、デッドコードの削除(コンパイラは通常、定数のたたみ込みを行うが、これにインライン展開を組み合わせることで良好な結果が得られる)
  • 線型走査レジスタ割り当て
  • SSAベースのフレームワーク(さまざまな最適化がこのフレームワーク上に実装されている)
 MonoチームはJITエンジンの改良を続けていますが、多くの最適化はプログラム実行時に行っても効果が得られません。アプリケーションの実行パターンのプロファイリングと調査を行えば、かなり良い結果が得られるでしょう。ソフトウェアのチューニング方法に関するさまざまなアイデアについては、Monoの「Performance Tips(パフォーマンスに関するヒント)」の記事を参照してください。

Mono 2.4のアーキテクチャ

 ここでは、Mono 2.4のアーキテクチャの各部分について説明します(図1を参照)。

Just-in-Time(JIT)エンジン

 Monoランタイムに含まれるJITエンジンは、MIPS(32ビットモードのみ)、x86、SPARC、PowerPC、ARM、S390(32ビットおよび64ビットモード)、IA64(64ビットモード)といった多くのプロセッサに対応しています。MonoランタイムはJITコンパイルの実行によってマシンのネイティブコードを生成し、その結果はアプリケーションの実行中にキャッシュされます。また、実行前にネイティブイメージをあらかじめキャッシュしておくことも可能です。

 ただし、Monoの現在の保守的ガベージコレクタ(Boehm-Demers-Wiser Conservative Garbage Collector)には、Java仮想マシンや.NET Frameworkランタイムのような、ガベージコレクションを実行する商用のランタイムに比べると大きな欠点があります。理論的にはメモリリークが発生する可能性があり、発生した場合にはメモリ不足によってアプリケーションが突然終了するおそれがあるのです。これは長期間にわたる実行が求められるサーバーアプリケーションにとって特に重大な問題です。現在、Monoチームは新たな「実用的」ガベージコレクタを開発していますが、これがプロダクションリリースに組み込まれる時期は未定です。

クラスライブラリ

 Monoのクラスライブラリは、アプリケーション開発に必要な包括的な機能セットを提供します。主にC#で書かれていますが、共通言語仕様のおかげで任意の.NET言語で使用することができます。クラスライブラリは複数の名前空間に分かれており、アセンブリと呼ばれる共有ライブラリ群に配置されています。.NET Frameworkへの参照は、基本的にこのクラスライブラリへの参照です。

名前空間とアセンブリ

 名前空間は、類似するクラスを論理的にグループ化して階層的な構造にするためのしくみです。これにより名前の競合を防ぐことができます。名前空間は単語の区切りにドットを使用して構成され、最上位の名前空間として最も一般的なのがSystemであり、その下にはSystem.IOやSystem.Netなどがあります。最上位の名前空間としては、他にもAccessibilityやWindowsなどがあります。ユーザーは、名前空間ブロックの中に要素を配置することで名前空間を定義できます。

 アセンブリは、クラスライブラリを物理的にパッケージ化したものです。Win32の共有ライブラリと同様(ただし混同してはなりません)、.dllファイルの形をとります。アセンブリの例として、mscorlib.dll、System.dll、System.Data.dll、Accessibility.dllなどがあります。名前空間は複数のアセンブリに分散していることが多く、1つのアセンブリは複数のファイルで構成できます。

共通言語インフラストラクチャと共通言語仕様

 一般的には共通言語ランタイム(CLR)として知られている共通言語インフラストラクチャ(CLI)は、Monoの実行ファイルによって実装されています。このランタイムは、コンパイル済みの.NETアプリケーションの実行に使用されます。共通言語インフラストラクチャは、ECMA規格によって定義されています。アプリケーションを実行するには、関連するパラメータを用いて共通言語ランタイムを呼び出す必要があります。

 共通言語仕様(CLS)は、ECMA-335の第6章で定められており、Enumの基本の型といった規則など、CLIに対するインターフェイスを定義しています。Monoコンパイラは、CLSに準拠した共通中間言語と呼ばれるイメージを生成します。Monoランタイムは、このイメージを受け取って実行します。ECMA規格では、CLAに準拠するライブラリをフレームワークとして正式に定義しています。

マネージドコードとアンマネージドコード

 ネイティブの.NET/Monoアプリケーション内では、すべてのコードが管理されます(つまり、メモリ管理およびスレッド安全性に関するCLIのスタイルに支配されます)。その他の.NETアプリケーションやMonoアプリケーションは、System.Runtime.InteropServicesライブラリを使用してC#バインディングを作成することで、アンマネージド(管理対象外)と呼ばれるレガシーコードを利用できます。Gtk#など、Monoに付随する多くのライブラリは、CLIのこの機能を使用しています。

選択肢としてのMono

 Monoは、絶え間なく改良が行われているオープンソースのプロダクトです。オープンソースや.NETの開発コミュニティでMonoプラットフォームが積極的に活用されることを願っています。ラピッドWebアプリケーション開発フレームワークを使ってプロジェクトのコストを抑えたい人にとっては、Monoは最適な選択肢の1つになるでしょう。

著者紹介

Tapas Pal(Tapas Pal)
インドのTata Consultancy Servicesに勤務する技術者。Microsoftのプラットフォームを専門とする。7年間の経験を持ち、.NET 1.1と.NET 2.0に関してMicrosoftの認定資格を取得している。

グループウェア導入の判断基準がわからない。あなたなら、どうする?
グループウェア導入の判断基準がわからない。あなたなら、どうする? 突然上司から、グループウェアを一新するからイチオシを挙げるよう言われた。急に言われても、何を基準に選べがいいか全くわからない。しかも、今まで以上にナレッジの蓄積と共有が促進されるものでないと駄目らしい。…そんな時には、「多機能」「低価格」「豊富な導入実績」の『J-MOTTOグループウェア』がオススメ。
J-MOTTOが4,200社に支持される4つの特長とは?上司の説得に役立つ資料を公開中!
プライバシー ジャパン・インターネットコム版
【プライバシー ジャパン・インターネットコム版】
使用を禁止されているUSBで検察官が公判資料紛失
Copyright 2010 internet.com K.K. (Japan) All Rights Reserved.