検索
連載

.NET 6統合の現状および概要と方向性.NET 6移行入門(1)

.NET 6の現状を把握し、具体的な移行方法を学ぶ連載。初回は、.NET 6の注目すべき新機能を中心に.NET 6の統合の現状および概要、方向性について。

PC用表示 関連情報
Share
Tweet
LINE
Hatena

 2021年11月9〜11日、「.NET Conf 2021」が開催され、「.NET 6」もとうとうローンチされました。偶数リリースの.NET 6はLTS(long-term support)となっており、そろそろ、.NET 6での新規アプリ開発や、既存アプリにおける.NET Frameworkから.NET 6への移行を検討する方も多いことでしょう。本稿では.NET 6の注目すべき新機能を中心に.NET 6の統合の現状および概要、方向性をお伝えします。

.NETプラットフォームの統合

 .NETプラットフォームの統合は、さかのぼること2年半、2019年5月6日にMicrosoftの公式ブログ「Introducing .NET 5」の中で、「.NET - A unified Platform」としてコンセプトが発表され、2020年11月の.NET 5のローンチで統合が完了する予定でした。

 .NET - A unified Platformのコンセプトは下記の通りです。

  • 1つのSDK、1つのランタイム、1つのコードベースで、クラウド、Web、デスクトップ、モバイル、ゲーム、IoT、AIなどのアプリを構築できる
  • .NETを学んだ後は、同じスキルで上記の全てのワークロードを構築できるようになる

 残念ながら2020年の.NET 5では、Xamarinの一部であるAndroid、iOS、およびmacOSの機能の統合は間に合わず、.NET 6での統合と延期されました。今回、.NET 6では、.NET 5で先送りになった統合が完了する予定でしたが、残念ながらまた延期となりました。ただし、今回はPreviewとして利用可能(※1)になっており、完全な統合まであと少しです(それまでは、従来のXamarinが更新され続け、本番用のモバイルアプリの構築にはXamarinが推奨されます)。

(※1)Previewとして、Windows版のVisual Studio 2022から.NET MAUI(※2)が利用可能です(Visual Studio 2022 for Macは未対応)。Visual Studio 2022 for Macでもios、android-aptのワークロード(Microsoft.iOS、Microsoft.Android)がPreviewで利用できます。

(※2).NET MAUIは、.NET Multi-platform App UIの略称です。Xamarin.Formsの後継のAndroid、iOS、macOS、およびWindows用の.NETを使用してネイティブクロスプラットフォームアプリを構築するUIです。

 具体的には、.NET MAUIのローンチが2022年第2四半期の初めを目標に延期されたことにより、.NET 6のiOS、Android、macOS、MacCatalystの各ワークロードのGAも2022年第2四半期の初めに延期となっています。

 あと半年程度で、ついに.NETにおけるプラットフォームの統合が完了し、.NET - A unified Platformが実現します。

 なお、Previewでは既に、Xamarin.Android、Xamarin.iOSの名称ではなく、Microsoft.Android、Microsoft.iOSが使用されています。

サポート

 .NET 6は2021年11年8日にリリースされ、LTSリリースとして3年間サポートされます(2024年11月8日まで)。

Version リリース日 リリースタイプ サポート期限
.NET 6 2021年11年8日 LTS 2024年11年8日
.NET 5 2020年11年10日 Current 2022年5年8日
.NET Core 3.1 2019年12年3日 LTS 2022年12年3日

 .NET 6は.NET Frameworkと.NET Coreが統合されてから最初のLTSリリースです。.NET Frameworkからの移行をどうすべきかについても気になるところでしょう(移行すべきかどうかの考え方については後述します)。

 サポートに関する詳細はこちらをご覧ください。

対応プラットフォーム

 動作プラットフォームはこちらの通りです。

Windows x86、x64、Arm64(クライアントのみ)
Linux x64、Arm32、Arm64
Android x64、Arm32、Arm64
iOS x64(シミュレーター)、Arm32、Arm64
Mac x64、Arm64

 対応プラットフォームに関する詳細はこちらをご覧ください。

.NET 6のターゲットフレームワークモニカ(TFM)

 新しいプラットフォームのサポートの追加で、TFMが追加されています。TFMとは「ターゲットフレームワークの呼称」という意味で、アプリまたはライブラリで使用できるようにするAPIのセットを表すものです。TFMはcsprojファイルのTargetFrameworkセクションに記載します。

 このように.csprojファイル内で定義します。

<TargetFramework>net6.0</TargetFramework>

 .NET 6にはOS固有のバインディングを含む下記のTFMがあります。

  • net6.0
  • net6.0-android
  • net6.0-ios
  • net6.0-maccatalyst
  • net6.0-macos
  • net6.0-tvos
  • net6.0-windows

 .NET Framework時代には、TFMから利用できるAPIが直感的に分からず非常に難解でしたが、ベースのTFM(net6.0)とOS固有のフレーバー(windows、Android、iosなど)によって構成されるよう整理され、とても分かりやすくなりました。

SDKワークロード

 TFMが、主要な機能とオプションの組み合わせで表現されることに合わせて、SDK自体も主要な機能と各ワークロードのオプションに分割されています。.NET 6では新たに追加された、.NET MAUI、Android、iOS、WebAssemblyが別のワークロードとして用意されています。これは、これまでのような全ての機能を含むモノリシックSDKでは、ビルド時間が長くなり、配布サイズも大きくなってしまうからです。

 SDKワークロードに関する詳細はこちらをご覧ください。

 「dotnet workload list」コマンドを実行すると、このようにインストールされている全てのワークロードが一覧表示されます。

Installed Workload Ids
----------------------
android-apt
ios
maccatalyst
macos
maui
tvos
wasm-tools

 .NET 7では、ASP.NETやWindowsデスクトップなどのコンポーネントもオプションになる予定です。

.NET 6のハイライト

 .NET 6のハイライトは、基本的に4つに集約されます。

  1. パフォーマンスの向上
  2. 開発生産性の向上
  3. セキュリティの脆弱(ぜいじゃく)性に対する緩和策の向上
  4. macOS、Arm64関連の対応

1.パフォーマンスの向上

 .NET 6ではランタイムに対するパフォーマンスの改善が多数あります。ゲーム開発者やライブラリ開発者にとっては詳細を理解することがとても有効ですが、業務アプリ開発者の場合、.NET 6をターゲットフレームワークにするだけでパフォーマンスの改善が見込めるので、移行するだけでもある程度のメリットを享受できます。

 .NET 6では、公開されているベンチマークによると、Entity Framework Coreのパフォーマンスは.NET 5と比べて最大92%速度を向上させており、Entity Framework Coreを利用している場合、既存の.NET Webアプリを.NET 6にマイグレーションするだけでも速度向上を見込めます。

 .NETでパフォーマンスの向上に注力する最大の理由は、「クラウドコンピューティングのコスト削減」です。少ないコンピューティングリソースで必要なパフォーマンスを実現できることで、クラウドのコストを最適化できます。

 以下、パフォーマンス改善の具体例を幾つか紹介します。

・インライン化による最適化

 「インライン化による最適化」は、コンパイラがメソッドの呼び出し先からコードを取得し、それを呼び出し元に直接出力するプロセスです。これにより、メソッド呼び出しのオーバーヘッドが回避されます。さらに呼び出し先のコードが結果として定数を返すような場合、コンパイル時に計算を完了させてしまい、呼び出し元のコンテキストに展開することで、メソッド呼び出し操作全体を定数に変換できます。

 ただし、インライン化すると全ての呼び出し元に呼び出し先の結果のコードがコピーされるので、内容的には同じコードだとしても、CPUから見れば別のコードとして扱われます。CPUのキャッシュメモリ上で多くのエビクション(キャッシュメモリからの削除)とロードが強制されて、かえって速度が低下してしまう場合もあります。それを最適化するために、コンパイラがインライン化するかどうか厳密に判断するように改善され、パフォーマンスを向上させています。

・IOの改善

 FileStreamの実装はとても古く、パフォーマンスに関連する多くの問題がありましたが、ほとんど手付かずのままでした。.NET 6ではFileStreamがほぼ完全に書き直されており、速度と信頼性が向上しています。また、複数のバッファーに対応した(Scatter/Gather IO)新しいAPIが導入されています。Scatter/Gather IOを使用すると、単一のsys-callで複数のバッファーを渡すことにより、高コストのsys-callの数を減らすことができます。

 Scatter/Gather IOは「ベクトル化 I/O」ともいい、単一のsys-callが複数のバッファーからデータを順次読み込んで単一のデータストリームに書き込む、またはデータストリームからデータを読み込んでベクトルで定義された複数のバッファーに書き込む入出力方式です。

・ディクショナリーの値が構造体の場合の処理の高速化

 新しいunsafeな「API - CollectionsMarshal.GetValueRefOrNullRef -」が追加され、ディクショナリー内の構造体の値をより速く更新できるようになりました。この新しいAPIは、一般的な業務アプリ開発ではなく、ゲーム開発やライブラリ開発など高性能なシナリオを想定しています。

 このAPIは、構造体の値の参照を返してその場で更新することができます。これまでは、構造体の値の更新には、辞書の検索と構造体のスタックへのコピーが必要で、高性能なシナリオではコストの問題がありました。今回の改良では、キーのハッシュ化が2回から1回に減り、構造体のコピー操作が全て不要になりました。

 なお、GetValueRefOrNullRefを利用する場合、Unsafe.IsNullRef(ref value)を使用してnull参照の確認が必要です。

 このAPI追加の背景を説明します。

 変更可能な構造体を利用する場合、誤って構造体をコピーしてしまい、元の構造体とコピー先の構造体の値が異なるものになってしまうトラブルが発生しがちです。これを防ぐには「構造体をコピーした上で値を変更し結果を元の場所にコピーして戻す」必要があります。これは小さな構造体なら問題ありませんが、構造体が大きい場合、高コストになります。そもそもパフォーマンス向上のために変更可能な構造体を使用する場合が多いので、いったんコピーして変更した上で再度元の場所にコピーし直すというのは本末転倒です。

 なお、.NET 5以降なら、List<T>に対しては、CollectionsMarshal.AsSpanメソッドでコレクションのSpanビュー(ref構造体)を取得できます。同じようにディクショナリーでもref構造体を取得できるようにするために、CollectionMarshal.GetValueRefOrNullRefという新しいAPIが提供されました。なお、この機能はinternalメソッドDictionary<TKey, TValue>.FindValueとして既に存在しており、.NET 6でGetValueRefOrNullRefメソッドとして公開されました

2.開発生産性の向上

 開発生産性の向上のために.NETインナーループのパフォーマンスが向上しています。「インナーループ」とは、コードの変更、ビルド、テストなどで繰り返し使用するプロセスのことです。

 インナーループの一部として頻繁に使用するツールやワークフローを最適化することで、ビルド時間の短縮、デバッグ時の手順の簡略化、実行中アプリの変更のライブ反映(Hot Reload)など、開発中の細かい待ち時間が短縮されました。コーディングの時間が増えることで生産性を高めることができます。

 Hot ReloadはWindows Formアプリ、WPF(Windows Presentation Foundation)アプリ、Webアプリ、MAUIアプリ(予定)が対応しています。

 また、new、build、runなどのdotnetコマンドを中心に、開発者のインナーループに関わる主要な部分のオーバーヘッドが削減されています。

3.脆弱性に対する緩和策の向上

 2021年の初頭に、.NETランタイムのセキュリティ対策のロードマップが発表されています。これらの脆弱(ぜいじゃく)性の緩和策は単なるセキュリティパッチではなく、ランタイムの構造に手を入れる根本的な対策を含んでおり、それらは.NET 6以降にのみ実装されます。.NET Frameworkのセキュリティパッチでは提供されません。

 なお、.NET 6では、以下の2つの重要な脆弱性緩和策がプレビューとなりました。なお、.NET 7ではこれらはデフォルトで有効になる予定です。

・Hardware-enforced Stack Protection(ハードウェア強制型スタック保護)

 ハードウェア強制型スタック保護は、Intel第11世代「Tiger Lake」プロセッサ、および「AMD Zen 3」プロセッサにControl-flow Enforcement Technology(CET)として搭載されているセキュリティ機能です。

 x64 CPUのハードウェアに依存した機能なので、x64プラットフォームでのみ有効化できます。CETはシャドースタック(コールスタックの「影(シャドー)」となる第2の別のスタック)を使って全てのリターンアドレスを記録しておく技術です。x64のアセンブリ言語で、CALL命令ごとにリターンアドレスがコールスタックとシャドースタックの両方にプッシュされ、RET命令ではコールスタックとシャドースタックの両方からリターンアドレスをロードします。

 2つのアドレスが一致しない場合、プロセッサは制御保護例外(#CP―Control-Protection Exception)を発行します。これがカーネルにトラップされ、セキュリティを保証するためにプロセスを終了させます。シャドースタックはリターンアドレスのみを格納するため、追加のメモリオーバーヘッドを最小限に抑えることができます。

・W^X(write xor execute:書き込みと実行の排他)

 W^Xは、プロセスやカーネルのアドレス空間内の全ページが、書き込み可能か実行可能かのいずれかであり、両方はできないというメモリ保護ポリシーです。この保護機能がないと、プログラムはデータ用のメモリ領域にCPU命令を書き込み(データ「W」として)、その命令を実行(実行可能「X」、または読み取り-実行「RX」として)することができてしまいます。

 W^Xは、最も単純な攻撃経路を遮断します。この機能がない場合、その他のより高度な脆弱性の緩和策はバイパスされる可能性があるので、その他の対策は意味がない結果となってしまいます。W^Xを導入したことで、今後CETのような他の補完的な緩和策が追加される予定となっています。

 W^Xは、.NET 6を搭載した全てのOSで利用可能ですが、デフォルトで有効なのは、Apple Silicon上で動くmacOSのみです。.NET 7では全てのOSで有効になる予定です。

macOS Arm64およびWindows Arm64に関するアップデート

 Windowsや.NETでは最近Arm64関連のサポートが強化されていますが、これは見逃せない動きです。Arm64プラットフォームはx64プラットフォームと比べて電力効率が非常に優れています。

 クライアントマシン1台レベルでは、消費電力の差はたかが知れていますが、クラウドのデータセンターの規模になるとその差は膨大になります。Arm64のサポートが今後進めば、クラウドでもArm64の利用がどんどん進むことでしょう。x86と併用される場合でも、同じ性能ならArm64の方が安くなる可能性が高いと予想しています。

 将来、x86からArm64に移行する流れが起こる可能性もあるので、Arm64の動向は注視することをお勧めします。

・SDK/ランタイム関連

 .NET 6では、x64およびArm64 .NETインストーラーがサイドバイサイドでインストールされるようになり(x64とArm64のビルドが別々の場所にインストールされます)x64とArm64が共存しています(これまでは、x64とArm64のビルドがお互いに上書きされてしまっていました)。

 macOSやWindowsのArm64マシンで、.NET 6 RC2以降を利用するには、Arm64とx64の.NET 6と以前の.NET(.NET 5、.NET Core 3.1など)の全ての.NET SDKとランタイムをいったんアンインストールして再インストールをする必要があります。なお、再インストール時に利用する以前のバージョンの.NET(.NET 5、.NET Core 3.1など)の.NET SDKとランタイムは今後提供される予定です。

 SDKは、Arm64では.NET 6以降のみがサポートされます。それ以前のSDKによるビルドはArm64ではブロックされます。ランタイムは、Arm64およびx64の全サポート中のバージョンがサポートされます。

 Windows Arm64用の.NET 5 SDKは、.NET 6 RTMに合わせて早期にサポートが終了します。

 Arm64アーキテクチャ上では、ネイティブアーキテクチャのパフォーマンスの享受、1つのSDKを管理すればよいなど、より良い体験ができるのでArm64 SDKの利用が推奨されています。

 なお.NET Frameworkでも、「.NET Framework 4.8.1」でArm64のサポートが追加されます。

・macOSユニバーサルバイナリー

 .NET 6では、ワークフローで.NETアプリのユニバーサルバイナリーをビルドできません。なお、この機能の必要性は.NET 7で再検討されます。

 現在、macOS向けとしてはIntel専用のバイナリーしかビルドできません。ユニバーサルバイナリーではないApple Silicon専用のバイナリーもビルドできません。ビルドしたIntel専用のバイナリーをRosetta 2を介してApple M1上で動作させることは可能です。

.NET 6に移行すべきか.NET Frameworkにとどまるべきか

 可能な限り.NET 6に移行することを推奨します。.NET 6で移行を見送る場合は、次のLTS、2023年の.NET 8リリースをターゲットに移行を進めておくことをお勧めします。

 移行に当たり、「.NET アップグレード アシスタント」を利用すると、SDKスタイルの.csprojへの移行、TFM(TFMについては後述します)のアップデート、NuGetパッケージの更新、テンプレートファイルやconfigファイルの追加などの定型的な移行についてのガイドが表示され、ステップ・バイ・ステップで自動的に移行を進めることができるので、移行作業の負荷が下がります。ただし、移行を完全に完了するためにさらに手作業での修正が必要です。

 なお、.NET アップグレード アシスタントで下記.NET Frameworkアプリの移行がサポートされています。

  • .NET Framework Windows フォーム アプリ
  • .NET Framework WPF アプリ
  • .NET Framework ASP.NET MVC アプリ
  • .NET Framework コンソール アプリ
  • .NET Framework クラス ライブラリ

 .NET Frameworkアプリを.NET 6以降に移行することを勧める最大の理由はセキュリティです。

パッチではない新たなセキュリティ対策は.NET 6以降にのみ実装される

 上記、セキュリティ対策のセクションで述べたように、既に.NET 6に新たなセキュリティ対策やHTTP/3など新たな注目すべき機能が実装され始めており、2年後の.NET 8(次のLTS)リリース時にはかなりの機能の差が拡大すると見込まれます。そして、これらの新機能は.NET Framework 4.8では提供されません。

 特にセキュリティ対策関連については、今後のロードマップが示されていますが、これらのセキュリティ対策は単なるセキュリティパッチではなく、CPUの新機能やランタイムの構造に手を入れる根本的な対策を含んでおり、それらは.NET 6以降にのみ実装されます。

 従って、次のLTSである.NET 8の世代では、.NET Framework 4.8はまだサポート期間内なので動作はするものの、セキュリティ対策の観点からはあくまでもパッチの提供にとどまり、新機能による根本的な対策は行われず、世代的に陳腐化すると考えられます。

 これらを加味した、移行の指針を以下に示します。

新規アプリなら.NET 6を選択

 いまだに、.NET 6を「枯れていない」という理由から避ける意見もありますが、.NET Coreの系統も、.NET 6で5世代目であり十分「枯れて」います。もはや新規アプリ開発のリスクは.NET Framework 4.8と差はないと考えて問題ありません。このタイミングで.NET 6を「枯れていない」として避けることは、逆に「ではいつになれば、枯れていると判断できるのか」ということになりキリがなくなってしまいます。

既存アプリもなるべく.NET 6に移行

 問題になるとしたら、既存アプリ移行のシナリオでサードパーティー製のライブラリが.NET 6に対応していない、開発元が既に存在しないというようなケースです。この場合、代替のライブラリを探したり、同等機能をスクラッチで開発しなければならかったりといったリスクがあります。

 サードパーティー製の.NET Framework対応ライブラリの保守も継続されるでしょうが、新規販売数が見込めないのであくまでも延命措置としての保守であり、今後サポートの優先度を下げられてしまうリスクも考慮すると、.NET 6に移行するのが賢明です。

.NET Frameworkのまま継続した方がよいケース

 例えば、当該アプリを稼働する環境が一切パブリックネットワークに接続しておらず完全に閉じた環境で使用されるアプリなら、そのままでもセキュリティ面のリスクも少ないので、ギリギリまで.NET Frameworkのまま維持し、そのまま終息させてしまう選択は有効です。

 よって、かなり限定されたケース以外では超えなければいけないハードルはあるにせよ、これから移行する場合にはこのタイミングで移行を開始し、2年後の.NET 8リリース時には移行完了するようなスケジュールを検討するのは良い選択と考えられます。

まとめ

 最後にまとめると、.NET 6で注目すべき動向はこの通りです。

  • .NET 6は安心して使える
  • 統合が一段落し、今後はセキュリティ脆弱性の緩和策や新機能にフォーカスしていく
  • CPUの新機能、OS、ランタイムの構造に手が入るセキュリティ脆弱性緩和策の実装が進んでいる
  • パフォーマンス向上=クラウドコンピューティングのコスト削減である
  • Arm64対応を積極的に進めている
  • Arm64による電力消費低減=将来的なクラウドコンピューティングのコスト削減に結び付くと予想される

 .NET 6を積極的に利用するメリットは十分にあるといえます。これまで移行に不安を抱えていた方も、このタイミングで再度.NET 6への移行を検討してはいかがでしょうか。

 また、将来的なArm64への移行もあり得えなくはない状況になってきました。こちらの動向も定期的に注視するのをお勧めします。

Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る