ツナ缶雑記

ぐうたらSEのブログです。主にマイクロソフト系技術を中心に扱います。

MSI BIOSでTPMを有効にする

f:id:masatsuna:20210625194613p:plain

Windows 11 が発表されましたね。 システム要件がいろいろ変わっていく中で、 TPM 2.0 が必須になったというのも時代の流れを感じます。 企業向けのモバイル PC とかだと、 TPM 2.0 があらかじめ有効になっているケースも多いと思いますが、個人用の PC だと無効になっているケースも多いのではないでしょうか。

今回は MSIBIOS で、 TPM を有効にする方法を解説します。

なお本稿で解説するのは、ファームウェア TPM という機能を有効にする方法です。 ハードウェア TPM を用いる方法もありますが、個人利用の範囲であればファームウェア TPM で十分だと思います(そもそもデスクトップ PC だと多くの人が無効にしているのではないかと思います)。

なお ASUS BIOSIntel CPU)については以下で解説しています。

tsuna-can.hateblo.jp

環境



TPM の設定状態を確認する

まずは Windows 10 を立ち上げて、 TPM の設定状態を確認します。 以下のように [tpm.msc] を検索してアプリを実行してください。

f:id:masatsuna:20210625191209p:plain

TPM が無効状態の場合は、以下のような画面になります。

f:id:masatsuna:20210625191333p:plain

こうなってしまっている場合は、 BIOS から TPM を有効にします。

BIOSTPM を有効にする

PC を起動して [Del] ボタンを連打し、 BIOS に入りましょう。 MSI マザーボードの場合は [Del] キー連打ですが、メーカーが違うと [F2] 連打、とか、仕様が異なります。

以降の説明は、日本語化した BIOS で説明します。 MSI マザーボードBIOS を日本語化する方法は以下のポストで解説しています。

tsuna-can.hateblo.jp

BISO 画面に入ったら、 [F7] を押下して [Advanced] に切り替えましょう。 そして [SETTINGS] > [Security] を選択します。

f:id:masatsuna:20210625192112j:plain

続いて [Trusted Computing] を選択します。

f:id:masatsuna:20210625192151j:plain

[Security Device Support] の項目が以下のように [Disable] になっていると思います。

f:id:masatsuna:20210625192305j:plain

この項目を選択して、以下のように [Enable] に設定します。

f:id:masatsuna:20210625192344j:plain

設定が完了したら、 [F10] を押下して保存しましょう。

f:id:masatsuna:20210625192423j:plain

[はい] を押下すると、自動的に PC が再起動します。

再度 TPM の設定を確認する

再起動したら、再度 TPM の設定を確認してみましょう。 [tpm.msc] を検索してアプリを実行してください。 すると、以下のように TPM 2.0 が有効になったことが確認できます。

f:id:masatsuna:20210625192556p:plain

おまけ

ついでなので Windows 11 がインストールできるかも確認してみましょう。 Windows 11 のインストールが可能かどうかは、[PC 正常性チェック] というアプリをインストールすると確認できます。 インストーラーは、 2021/06/27 現在、以下からダウンロードできます。

このアプリは現在新しくなっています。 記事内の画像は初期バージョンのものですのでご注意ください。

https://aka.ms/GetPCHealthCheckApp

このアプリを実行すると、以下のような項目が表示されます。

f:id:masatsuna:20210625192906p:plain

[今すぐチェック] ボタンを押下すると、システム要件のチェックが自動的に行われます。 TPM を有効にした状態でこのチェックを行うと、以下のように Windows 11 のインストールができると表示されました。

f:id:masatsuna:20210625193008p:plain

これで安心して Windows 11 のリリースを待てそうです。

Windows 11 のインストール手順

実際に Windows 11 を VM にインストールしてみました。 その際の手順や、 TPM 無効時の挙動などはこちらからどうぞ。

tsuna-can.hateblo.jp

Azure Pipelines で Markdown から静的 Web サイトを生成してStorage Accountに公開する(mkdocs)

f:id:masatsuna:20210624080015p:plain

前回は mkdocs を使って静的な Web サイトを Markdown を用いて生成しました。

tsuna-can.hateblo.jp

今回はこれを Azure DevOps を使って、 Azure Storage Account の静的 Web サイトに発行する手順を解説します。

環境

  • Azure DevOps
  • Storage Account(静的 Web サイト)

Storage Account の 静的 Web サイトとは

Storage Account にアップロードしたファイルを、 Web に公開してくれる機能です。 サーバー側は、ただ静的ファイルを公開する機能しか持たないため、サーバー再度で何らかの処理を行うことはできません。 JavaScript のように、クライアント側で実行するものは使えますが、あくまで静的なファイルを配信する目的にしか使えません。

またファイルの配置先は Storage Account となるため、 Web アプリケーション自体の認証機能が弱いです。 Azure AD と接続して認証させたいとか、細かな制御ができません。 同じような機能を提供してくれる Static Web Apps というものもありますので、要件に合わせてよい方法を選択してもらえればと思います。

ディレクトリ構造

今回作るディレクトリの構造は以下のようなものになります。

ルートディレクトリ
├ mkdocs.yml
├ docs
│  └ index.md
└ pipelines
   └ markdown-build.yaml

Markdown を作る

今回は Azure Pipelines で静的 Web サイトを発行することが目的なので、作成する Markdown は初期のものをそのまま使います。 mkdocs.yml と index.md が mkdocs で生成したファイルです。 詳細は前回の記事を参照してください。

Azure Pipelines 用の YAML を作る

markdown-build.yaml ファイルに、 mkdocs のビルドを行うための設定を記述していきます。 今回は mkdocs による静的 Web サイトの生成と、 Storage Account の静的 Web サイトへの発行の 2 ステップを行います。 説明を簡略化するため、 Multi Stage Pipeline は利用していないことに注意してください。

構築する YAML の全体像は以下のようになります。

trigger: none

pool:
  vmImage: ubuntu-latest

steps:
  - task: PowerShell@2
    displayName: "MkDocs のインストールと実行"
    inputs:
      targetType: 'inline'
      script: |
        python -m pip install wheel
        python -m pip install mkdocs
        python -m pip install mkdocs-material
        python -m pip install mkdocs-minify-plugin
        python -m mkdocs build
  - task: AzureCLI@2
    displayName: '静的Webサイトの更新'
    inputs:
      azureSubscription: '<サービスコネクションの接続名>'
      scriptType: 'pscore'
      scriptLocation: 'inlineScript'
      inlineScript: |
        Param($StorageAccountName, $ContainerName, $UploadDirectory)
        az storage blob delete-batch --source $ContainerName --account-name $StorageAccountName
        az storage blob upload-batch --destination $ContainerName --source $UploadDirectory --account-name $StorageAccountName
      arguments: 
        -StorageAccountName '<ストレージアカウントの名前>'
        -ContainerName '$web'
        -UploadDirectory '$(Build.SourcesDirectory)/site'

以下、部分ごとに解説していきます。

Python のインストール要否

今回は ubuntu-latestVM を利用するため、 PythonVM イメージにインストール済みです。 この記事を書いている時点では、 Python 3.8.5 がインストールされていました。 また pip についてもインストール済みです。

VM イメージにインストールされているソフトウェアは、以下のページから参照することができます。

docs.microsoft.com

もっと新しいバージョンの Python を使いたい場合は、自分で Python をインストールするようにしましょう。

mkdocs のインストール

Python 同様、 pip も ubuntu-latest のマシンにはプリインストールされています。 また PowerShell もインストールされています。 ということで、 PowerShell のタスクを使って、必要となるパッケージをインストールしています。

  - task: PowerShell@2
    displayName: "MkDocs のインストールと実行"
    inputs:
      targetType: 'inline'
      script: |
        python -m pip install wheel
        python -m pip install mkdocs
        python -m pip install mkdocs-material
        python -m pip install mkdocs-minify-plugin

mkdocs の実行

前述のタスクの最後に、 mkdocs を使って静的 Web ページを生成しています。 以下の個所がそれです。

python -m mkdocs build

このコマンドを実行することで、 mkdocs.yml ファイルのあるディレクトリに、 site という名前のディレクトリが生成され、その中に静的 Web サイトの HTML や CSS などのコンテンツが出力されます。

Azure Blob Storage の作成

ここまでで静的 Web サイトとして発行するための資材は完成しました。 続いて静的 Web サイトを発行する先の Azure のリソースである Blob Storage を作成します。

普通に Azure Portal から Blob Storage のリソースを 1 つ作成します。 作成が完了したら、 Blob Storage に対して静的 Web サイトの機能を有効にします。

まず Storage Account の画面に入って、左側のメニューから [データ] > [静的な Web サイト] を選択します。

f:id:masatsuna:20210621234142p:plain

続いて右側のブレードで [静的な Web サイト] を [有効] に設定し、以下のように設定します。

項目 設定値
インデックス ドキュメント名 index.html
エラー ドキュメントのパス 404.html

f:id:masatsuna:20210621234433p:plain

この状態で左上にある [保存] ボタンを押下します。 すると画面が以下のようになり、 Web サイトを公開している URL が表示されます。

f:id:masatsuna:20210621234834p:plain

この状態で、すでに Web サイトが立ち上がっています。 URL に対してブラウザーからアクセスすると、 404 が返ってくることがわかると思います。

静的な Web サイトの機能を有効にすると、 Storage Account に 「$web」という名前のコンテナーが自動的に作成されます。

f:id:masatsuna:20210622001351p:plain

このコンテナーに Web サイトの資材を配置すると、 Web ブラウザーから閲覧できるようになります。 これで Azure のリソース準備は完了です。

サービスコネクションの作成

続いて Azure DevOps から Azure Blob Storage に接続できるように設定していきます。 Azure DevOps の組織の管理者であり、 Azure サブスクリプションの所有者でもあるアカウントであれば、すごく簡単にサービスコネクションの設定が可能です。 以下の記事で設定手順を解説しています

tsuna-can.hateblo.jp

本家サイトでは、以下に解説があります。

docs.microsoft.com

docs.microsoft.com

サービスコネクションを作成したら、その接続名を控えておきましょう。 あとで使用します。

Azure Blob Storage の更新

再度 Azure Pipelines の YAML に戻り、作成したサービスコネクションを経由して、 Azure Blob Storage に静的 Web サイトを配置できるようにしていきます。 ubuntu のマシンから Azure のリソースに接続する場合は Azure CLI のタスクを利用します。 今回は PowerShell Core を使ってアクセスするように設定しています。 また azureSubscription には、先ほど作成したサービスコネクションの接続名を設定します。

  - task: AzureCLI@2
    displayName: '静的Webサイトの更新'
    inputs:
      azureSubscription: '<サービスコネクションの接続名>'
      scriptType: 'pscore'
      scriptLocation: 'inlineScript'
      inlineScript: |
        Param($StorageAccountName, $ContainerName, $UploadDirectory)
        az storage blob delete-batch --source $ContainerName --account-name $StorageAccountName
        az storage blob upload-batch --destination $ContainerName --source $UploadDirectory --account-name $StorageAccountName
      arguments: 
        -StorageAccountName '<ストレージアカウントの名前>'
        -ContainerName '$web'
        -UploadDirectory '$(Build.SourcesDirectory)/site'

今回は Blob Storage の「$web」というコンテナーに対して、静的 Web サイトを配置する前に全削除を行い、ビルドした資材を再度アップロードする、という方法で更新していきます。 Blob Storage のデータを削除したり更新したりする場合、 az storage blob というコマンドを使ってアクセスします。 Azure CLI のタスクを使用すると、 Azure へのログインは自前で行わなくても、タスク側で自動的に実行してくれます。 ですので、やりたい処理をそのまま書くだけで問題ありません。 特定のコンテナーからファイルを全件削除する場合、 az storage blob delete-batch コマンドを、ローカルディレクトリ内の全ファイルをアップロードする場合 az storage blob upload-batch コマンドを使うと便利です。

またアップロードする静的 Web サイトは、 mkdocs によってビルドした site ディレクトリ配下のものを指定しています。 今回はルートディレクトリ内に mkdocs.yml を配置しているため、ルートディレクトリ( $(Build.SourcesDirectory) の変数に設定されているパス)直下に生成される site ディレクトリをアップロード対象のディレクトリとして指定しています。

実行してみる

うまく設定ができていれば、ビルドパイプラインを実行すると、 Blob Storage の静的 Web サイトが更新されます。

f:id:masatsuna:20210622003518p:plain

存在しない URL をたたいた場合も、ちゃんと 404 ページが表示されていい感じです。

f:id:masatsuna:20210622003625p:plain

まとめ

今回は mkdocs を Azure Pipelines から実行して、 Blob Storage の静的な Web サイトに発行する手順を書きました。 CI トリガーを設定しておけば、 Git リポジトリを更新したら Web サイトを即時反映することもできちゃいますね。 Blob Storage の制約が気にならないのであれば、格安で情報共有サイトが作れます。 もしその辺の制約が気になるのであれば、 Static Web Apps とかも検討してみるとよいと思います。

本稿で解説した YAML について

原本は以下の GitHub リポジトリに公開してあります。

AzurePipelinesYAMLSample/MkdocsAndPublishToBlobStorage at master · tsuna-can-se/AzurePipelinesYAMLSample · GitHub

Markdown を使って静的 Web サイトを作る

f:id:masatsuna:20210615003957p:plain

簡単な Web サイトを手間なく作ろうとしたとき、皆さんならどうやって作りますか? デザインにこだわる時間はないし、とにかく早く Web サイトを公開しなければならない、というユースケースにおいて、 MkDocs というツールは非常に強力です。

今回は MkDocs を使って、 Markdown から静的 Web サイトを作る方法について、 Windows 環境で解説します。 超初心者向けの最初の一歩となる内容ですので、すでに詳しい方はそっと閉じていただけると助かります。

環境

環境構築

Python のインストール

以下のサイトからインストーラーをダウンロードします。

www.python.org

今回は Windows 10 64bit 環境で行うので、 Windows 64bit 用のインストーラーを以下からダウンロードします。

https://www.python.org/downloads/windows/

f:id:masatsuna:20210610162801p:plain
インストーラーのダウンロード

インストーラーを起動したら、 Pythonコマンドラインから使いやすくするために [Add Python 3.9 to PATH] にチェックを入れてインストールしましょう。

f:id:masatsuna:20210610163033p:plain
インストールの実行

pip の更新

続いて Python のパッケージマネージャーである pip の更新をします。 コマンドプロンプトを管理者権限で起動し、以下のコマンドを実行します。

pip install --upgrade pip

mkdocs のインストール

続いて pip を使って、 mkdocs というパッケージをインストールします。 コマンドプロンプトを起動して、以下のコマンドを実行します。

pip install mkdocs

パッケージのダウンロードが実行されます。 コマンドの実行完了後、以下のように mkdocs のバージョン確認ができればインストール完了です。

C:\Windows\system32>mkdocs --version
mkdocs, version 1.2.1 from c:\users\<ユーザー名>\appdata\local\programs\python\python39\lib\site-packages\mkdocs (Python 3.9)

プロジェクトの作成

プロジェクトルートとなるディレクトリを適当に作成しましょう。 コマンドプロンプトで作成したディレクトリに移動し、以下のコマンドを実行します。

mkdocs new .

コマンド中の「.」は、カレントディレクトリをルートディレクトリとしてプロジェクトを作成することを表しています。 「.」の代わりにディレクトリ名を入れることもできます。 その場合、カレントディレクトリに設定した名前のディレクトリが生成され、その中にプロジェクトが生成されます。

Markdown の編集

mkdocs new コマンドでプロジェクトを作成すると、以下のようにファイルやディレクトリが生成されます。

プロジェクトルート
├ mkdocs.yml
└ docs
    └ index.md

docs ディレクトリの中に Markdown ファイルを配置していきましょう。 今回はサンプルなので、特に編集はしません。

なお Markdown の編集には、 Visual Studio Code が非常に便利です*1

mkdocs.yml とは

mkdocs.yml ファイルは、このプロジェクトの設定を行うためのファイルです。 開いてみると、以下のような設定が記載されています。

site_name: My Docs
site_url: https://example.com/

最低限この 2 つの設定があれば、静的 Web サイトの生成を行うことができます。 site_url は、実際に静的 Web サイトを発行する先の URL を入力しておきます。 ただし、ローカル環境でテスト実行するのみであれば、特に設定は何でも構いません。

テスト実行

それでは作成したプロジェクトを使って、テスト実行をしてみましょう。 コマンドプロンプトで、先ほど作成したプロジェクトルートのディレクトリを開き、以下のコマンドを実行します。

mkdocs serve

すると、 mkdocs に組み込みの Web サーバーが起動して、ブラウザーから確認することができるようになります。 Markdown や mkdocs.yml に記載ミスがなければ、Web サーバーが起動し、コマンドプロンプトにその URL が表示されます。

c:\tsuna-can\repos\MarkdownSample>mkdocs serve
INFO     -  Building documentation...
INFO     -  Cleaning site directory
INFO     -  Documentation built in 0.16 seconds
INFO     -  [17:05:40] Serving on http://127.0.0.1:8000/

実際にブラウザーから表示されている URL を見に行くと、以下のように Markdown が 静的 Web ページに変換され、表示できてしまいます。

なおこの Web サーバーは、ホットリロードに対応しています。 Web サーバーが起動している状態で、 Markdown のファイルや mkdocs.yml を変更すると、即時ブラウザーに変更が反映されます。

f:id:masatsuna:20210610170633p:plain

Markdown を静的 Web サイトに変換する

先ほどはテスト用の Web サーバーを使用して、静的 Web サイトを参照しました。 Markdown から HTML に変換して、既存の Web サーバーに配置するためのファイル群を生成することもできます。 HTML などのファイル群を生成する場合は、以下のコマンドを実行します。

mkdocs build

ビルドが完了すると、カレントディレクトリの中に site ディレクトリが生成され、その中に Markdown を HTML に変換したファイル一式が生成されます。 このファイル群を Web サーバーに配置すると、先ほどテスト用サーバーで実行したものと全く同じサイトを閲覧できます。

プロジェクトのカスタマイズ

ここまでは mkdocs のチュートリアルみたいなものです。 mkdocs はかなり豊富な拡張パッケージがあります。 また mkdocs.yml に設定を行うことで、細かくカスタマイズを行うこともできます。

テーマを変更する

まずは生成する Web サイトのテーマを選定することから始めましょう。 テーマによって設定項目が大きく異なることがあるため、最初にテーマを決めることをお勧めします。

mkdocs には、デフォルトで2つのテーマが組み込まれています。 テーマの設定は、 mkdocs.yml に行います。 theme > name に使用するテーマの名前を指定します。 既定では mkdocs と readthedocs が使えます。 既定値は mkdocs です。

site_name: My Docs
site_url: https://example.com/
theme:
    name: readthedocs

上記のような感じでテーマを設定すると、生成される Web サイトのデザインが、以下のように全く異なるものになります。

f:id:masatsuna:20210615000220p:plain
readthedocs のテーマを選択した場合

追加のテーマのインストールと設定

Material for MkDocs のインストール

mkdocs では、追加のテーマを入れて、さらなるカスタマイズを行うことができます。 最も有名なのが、 Material for mkdocs というテーマで、 Google の Material デザインを意識しています。

squidfunk.github.io

インストールは非常に簡単で、以下のコマンドを実行するだけです。

pip install mkdocs-material

テーマの設定

インストールが完了したら、 mkdocs.yml に、インストールしたテーマを利用するよう設定を行いましょう。 設定方法は先述したテーマの設定箇所と同じです。

site_name: My Docs
site_url: https://example.com/
theme:
  name: material

このような設定を行うと、 Web サイトのデザインが Material デザインに変更されます。

f:id:masatsuna:20210615001225p:plain
material のテーマを選択した場合

言語の設定

Material for MkDocs を選択した場合、必ず最初にやっておいた方が良いのが言語の設定です。 theme > language に ja を設定しましょう。

site_name: My Docs
site_url: https://example.com/
theme:
  name: material
  language: ja

これで Web サイトが日本語化されます。

f:id:masatsuna:20210615001730p:plain

今まで英語表記だった箇所が日本語翻訳されます。 また Web サイト自体の言語も日本語に設定されるため、 ChromeChromium Edge が翻訳を促す小窓を無駄に出してくることもなくなります。

その他の設定

Material for MkDocs には多種多様な設定項目があります。 ここではそのすべてを解説しきることができません。 詳細は本家のサイトをご覧ください。

squidfunk.github.io

なお、様々なカスタマイズ項目がある Material for MkDocs ですが、一部の設定項目はインサイダーと呼ばれる課金ユーザー向けのものになっています。 詳細は以下をご覧ください。

squidfunk.github.io

まとめ

今回は Markdown を使って静的 Web サイトを作成する方法について解説しました。 デザインはテーマ任せとなってしまいますが、そもそもデザイン作業自体が苦手な方や、記事の内容に注力したいケースでは、非常に使い勝手の良いツールであると思います。 Markdown だけである程度見た目の良い Web サイトを生成してくれるのは魅力的ですね。

*1:こちらについては今回特に必須ではないため解説しません。

インターフェースを実装しているクラスやメソッドを楽に探す方法(Visual Studio 2019)

f:id:masatsuna:20210614104456p:plain

インターフェースや抽象クラスを用いたソースコードを書いているときの問題点として、コードを読んだときにどの具象クラスが実行されるのか、パッと見たときわからない、という問題があります。 DI を用いている場合は、特にインターフェースをゴリゴリ使うことになるので、コードレビューで人のコードを眺めるのも結構めんどくさいんですよね。 参照されている個所一覧を見て、力業で探し出すというやり方が個人的には一般化していました。

Visual Studio 2019 で、ついにこの問題に対する解決策が提示されました。 インターフェースやメソッドを実装しているクラス、メソッドを一覧表示してくれるようです。 まだプレビューの機能ではありますが、使ってみた感じは非常に良いです。 インターフェースを活用したプロジェクトを触っているなら、ぜひ使ってみてください。

devblogs.microsoft.com

環境

設定方法

この機能はプレビュー機能であり、設定で明示的に有効にしないと使えません。 まず [ツール] > [オプション] を選択して [オプション] ダイアログを開きます。 左側ペインで [テキストエディター] > [C#] > [詳細] を選択します。 右側ペインの下部にある [継承の余白を表示する] というチェックをオンにします。

f:id:masatsuna:20210614094906p:plain

日本語翻訳が意味不明ですが、多分「継承の範囲を表示する」という意味なんだと思います。 英語表記だと「Show inheritance margin」となっていますね。 いずれにせよこのチェックをオンにすると使えるようになります。

動作確認

今回は簡易な動作検証を目的とするため、以下のようなクラス構造、プロジェクト構造とします。

f:id:masatsuna:20210614095836p:plain

プロジェクトとしては 3 つあります。 CoreLib プロジェクトにインターフェース(IBookRepository)を定義します。 CoreLib プロジェクトを参照する Infra プロジェクトに、 IBookRepository を実装した BookRepositoryImpl クラスを定義します。 ShowInheritMarginTest プロジェクトは Infra プロジェクトと CoreLib プロジェクトを参照しており、 IBookRepository を実装したテスト用の TestBookRepository クラスを定義します。

こんなシナリオで、 IBookRepository インターフェースを Visual Studio 2019 上から参照すると、以下のようになります。

f:id:masatsuna:20210614100311p:plain

コードファイルの左側に、見慣れないアイコンが表示されています。 このアイコンを押下すると、そのインターフェースまたはメソッドを実装しているクラスやメソッドの一覧を表示できます。

インターフェースの部分のアイコンを押下すると、以下のようになります。

f:id:masatsuna:20210614100450p:plain

またメソッドの部分のアイコンを押下すると、以下のようになります。

f:id:masatsuna:20210614100533p:plain

ちゃんと継承しているクラスやメソッドを一覧表示してくれます。 そしてこの表示されているリストから移動したいものを押下すると、そのメソッドやインターフェースに移動してくれます。

プロジェクトが別のものであっても、ちゃんと検索して表示してくれます。 クリーンアーキテクチャを採用して、プロジェクト構造をしっかり作りこむと、こういう構成って割と普通になりますよね。 そんなケースでも問題なく使えるのは非常に助かります。

ちなみに [Ctrl] + [F12] のキーボードショートカットでも同じような機能が使えます。 どちらもできることはほぼ同じですので、使いやすい方を選べばよいと思います*1

まとめ

Visual Studio 2019 に追加された個人的に超おすすめの新機能をご紹介しました。 これでインターフェースを活用したプログラムのコードリーディングがはかどりそうです。

*1:私はすぐにキーボードショートカットを忘れてしまうので、マウス操作できるとありがたいです。

メモリの速度は.NETアプリケーションのビルド時間に影響を与えるのか

f:id:masatsuna:20210608201002p:plain

Ryzen シリーズの特徴として、メモリの速度が重要であると言われてきました。 様々なベンチマーク結果を見る限り、メモリの速度を上げることで、 CPU の処理性能を向上させることができているようです。 では実際の .NET アプリケーションのビルドというユースケースにおいて、メモリの速度がどの程度の影響を及ぼすのか調査してみた、というのが今回の趣旨となります。

環境

今回検証に使用するマシンは以下の通りです。

項目
CPU AMD Ryzen 9 5900X(PBO は自動に設定)
メモリ DDR4 32GB × 2枚(3200MHz)デュアルランク
記憶装置 1TB NVMe M.2 SSD(PCIe 4.0)
マザーボード MSI B550 TOMAHAWK
CPUクーラー Nocture NH-D15

この PC に対して、 BIOS でメモリの動作速度を変更し、その影響を確認します。 メモリ速度は、このメモリの SPD に記録されていた 2133MHz と、 Ryzen 9 5900X のサポートする最大値である 3200MHz を使用します。 3200 MHz の方は、XMP に入っている設定をそのまま使用します。 詳細は以下の通りです。

項目 SPD 設定 OC(XMP) 設定
速度 2133 MHz 3200 MHz
モリタイミング 15-15-15-36 16-20-20-38
電圧 1.2V 1.35V

なお使用しているメモリは以下のものです。


検証内容

検証は .NET 5 のアプリケーションをビルドし、ビルド時間を比較する方法で行います。 対象のソースコードは、 2021 年 5 月下旬に取得したものを使用します。 各アプリケーションは、 NuGet パッケージを参照しているため、事前にパッケージをすべてローカルにダウンロードした状態でビルドを行います。 ローカルファイル内にパッケージがあれば、ダウンロードする処理は行われないため、ネットワークの影響を限りなく無視することができます。

今回検証の対象となるアプリケーションは、以下の 2 つを利用します。

eShopOnWeb

github.com

こちらはマイクロソフト社が開発している .NET Core のリファレンスとなるアプリケーションです。 リファレンスとして使用するもので、プロジェクトの数も 9 つしかありません。

Entity Framework Core

github.com

.NET Core で使用できる代表的な O/R マッパーです。 こちらはそれなりに規模が大きく、 46 プロジェクトで構成されています。

検証手順

eShopOnWeb

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

dotnet restore eShopOnWeb.sln

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

dotnet build eShopOnWeb.sln

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 8 回ずつ実行します。

Entity Framework Core

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

restore.cmd

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

build.cmd

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 6 回ずつ実行します。

検証結果

eShopOnWeb のビルド時間

f:id:masatsuna:20210606074104p:plain

Entity Framework Core のビルド時間

f:id:masatsuna:20210606074117p:plain

結果を見てみましょう。 平均値で見比べると、やはりメモリの速度を上げることで、処理性能を引き出すことができるようです。 これまでの検証結果とも同じ傾向で、規模の小さなプロジェクトの場合はあまり影響を受けず、規模が大きくなるほど影響が大きくなります。

考察

今回はメモリの動作速度にだけ注目して検証を行いました。 Ryzen はメモリの動作速度が PC 全体のパフォーマンスに影響を与える、という説は、ここでも実証された形になります。

一般的にプログラムをコンパイルするという処理は、メモリを大量に使って処理を進める傾向にあります。 そのため、メモリのスピードを変更しただけでも、明らかにスピード差が生まれているものと推測します。 とはいえ、 CPU の差ほど大きな差がつくわけではないため、コストをかけるのであれば、まずは CPU を強化し、メモリは後回し、という考え方はいつも通り成り立つものと思います。

いずれにせよメモリの速度を上げることで、ビルド時間を多少でも短縮することができますので、チャレンジしてみる価値はあると思います。 なお私の PC に搭載しているメモリは、 3200MHz が最高設定ということになっているので、これ以上のオーバークロックは試していません*1。 メモリのオーバークロックによる効果も気になるところではありますが、今回の結果を見る限り、あまり大きな差は出ないものと思われます。

まとめ

今回は、メモリの速度が .NET アプリケーションのビルド時間にどの程度の影響を与えるか検証してきました。 CPU 程ではないにせよ、メモリの速度を上げることで、 .NET アプリケーションのビルド時間を短縮する効果が確認できました。 メモリの速度調整は、 XMP のおかげで比較的簡単に実施できます。 無理のない範囲でメモリ速度のチューニングを行ってみるのもよいかもしれませんね。

というわけで、今回で .NET アプリケーションのビルド時間を検証する企画は終了です。 個人的に気になるデータをいろいろ収集できて満足でした。

*1:いまはメモリも高いですし、壊したくないです。

モバイルノートPCは.NET開発に使えるのか

f:id:masatsuna:20210606055332p:plain

本シリーズのまとめはこちらにあります。

tsuna-can.hateblo.jp

前回まで、 CPU の差異や、コア数の差異による .NET Core アプリケーションのビルド時間を計測、検証してきました。 これまでの検証結果から、 CPU を最新世代の強いものに変えること、 8 Core 以上の CPU を用意することで、ビルド時間の短縮に大きな効果が得られることがわかっています。

tsuna-can.hateblo.jp

tsuna-can.hateblo.jp

tsuna-can.hateblo.jp

ここまでは、デスクトップ PC におけるビルド時間の検証を主に行ってきました。 しかし、最近はモバイルノート PC で開発を行う機会が増えてきていると思います。 一昔前とは異なり、モバイルノート PC の性能は大きく向上しており、開発作業ができなくはないレベルになってきていると、個人的には実感しています。 ただ、その実感というのが、デスクトップ PC と比較したときにどうなのか、という点は、私自身あまり検証したことがありませんでした。 今回は、第 10 世代の Intel モバイルノート向け CPU を搭載したノート PC (Surface Laptop 3)と、同世代のデスクトップマシンで、ビルド時間の比較を行ってみようと思います。

環境

今回検証に使用するマシンは以下の通りです。

項目 Surface Laptop 3 9th Core i7 構成 Zen3 Ryzen 構成
CPU Intel Core i7 1065G7 Intel Core i7 9700K AMD Ryzen 9 5900X(PBO は自動に設定)
メモリ LPDDR4x 16GB DDR4 8GB × 2枚(2666MHz) DDR4 32GB × 2枚(3200MHz)
記憶装置 256GB SSD 1TB NVMe M.2 SSD(PCIe 3.0) 1TB NVMe M.2 SSD(PCIe 4.0)
マザーボード - ASUS TUF Z390-PLUS GAMING MSI B550 TOMAHAWK
CPUクーラー - Nocture NH-U12A Nocture NH-D15

ちなみにこれらの CPU の Cinebench R23 におけるベンチマークを以下に貼っておきます。

項目 Intel Core i7 1065G7 Intel Core i7 9700K AMD Ryzen 9 5900X
Multi Core 4,475 9,214 21,878
Single Core 1,153 1,246 1,622

Core i7 1065G7 はモバイルノート PC 向けの省電力 CPU です。 TDP も 15W と圧倒的に少なく、性能面では、比較するまでもなく大きな隔たりがあります。 この CPU はデスクトップ CPU とどの程度戦えるのか、というのが今回のメインテーマとなります。

なお Surface Laptop 3 はすでに在庫限りとなっており、各社通販サイトでも、今回使用したモデルはもう購入できないようです。 別スペックの物は 2021/6/4 現在、まだ在庫があるようですね。


なお Surface Laptop シリーズは、第 11 世代の Intel モバイルノート向け CPU または Zen2 世代の Ryzen のモバイル向け CPU を積んだ新しいモデルが登場しています(Surface Laptop 4)。 今回検証で使用する PC は、世代としては 1 つ前の物ではありますが、まだまだ現役最強クラスの性能を持つモバイルノート PC の 1 つであると思います。


検証内容

検証は .NET 5 のアプリケーションをビルドし、ビルド時間を比較する方法で行います。 対象のソースコードは、 2021 年 5 月初旬に取得したものを使用します。 各アプリケーションは、 NuGet パッケージを参照しているため、事前にパッケージをすべてローカルにダウンロードした状態でビルドを行います。 ローカルファイル内にパッケージがあれば、ダウンロードする処理は行われないため、ネットワークの影響を限りなく無視することができます。

今回検証の対象となるアプリケーションは、以下の 2 つを利用します。

eShopOnWeb

github.com

こちらはマイクロソフト社が開発している .NET Core のリファレンスとなるアプリケーションです。 リファレンスとして使用するもので、プロジェクトの数も 9 つしかありません。

Entity Framework Core

github.com

.NET Core で使用できる代表的な O/R マッパーです。 こちらはそれなりに規模が大きく、 46 プロジェクトで構成されています。

検証手順

eShopOnWeb

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

dotnet restore eShopOnWeb.sln

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

dotnet build eShopOnWeb.sln

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 7 回ずつ実行します。

Entity Framework Core

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

restore.cmd

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

build.cmd

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 7 回ずつ実行します。

検証結果

eShopOnWeb のビルド時間

f:id:masatsuna:20210605173702p:plain

Entity Framework Core のビルド時間

f:id:masatsuna:20210605173713p:plain

結果を見てみましょう。 どちらの結果をみても、明らかに Surface Laptop 3 の Core i7 1065G7 の性能が悪いことがわかります。 eShopOnWeb の方は約 5.8 秒遅く、 Entity Framework Core の方に至っては約 39 秒も遅いです。

考察

モバイルノート PC 向けの CPU とデスクトップ PC 向けの CPU では、ほぼ同じような世代の中でも大きな差がつくことがわかりました。 正直な話、こうなることは、やる前からある程度想像がついていました。 CPU のベンチマークを見てみても、圧倒的な性能差があります。 また Core i7 1065G7 は、 4 コア 8 スレッドで、コア数もスレッド数も、デスクトップ PC 向けの CPU とは差があります。 要するに、勝てる要素は何ひとつないわけです。 そうであるなら、こういった結果になるのはある意味妥当であると考えられます。

ベンチマークの結果で見比べると、最新世代のモバイルノート PC 向け CPU は、私が以前使っていた Core i7 4790K とほとんど同じようなスコアです。 どちらも 4 コア 8 スレッドで、シングルスレッドの性能は Core i7 1065G7 のほうが少し上、マルチスレッドの性能は Core i7 4790K のほうが少し上、という感じです。 当時検証したものと全く同じコードではないため、今回の比較対象からは外していますが、おおよそ同程度の時間、ビルドにかかっています。 CPU のベンチマークというのは割といい線ついているんだなーというのがわかります。 以前の検証結果はこちらから確認できます。

tsuna-can.hateblo.jp

モバイルノート PC で大規模なプロジェクトの開発は無理がある

話を今回の比較に戻します。 この結果からわかることとして、大規模なプロジェクトの場合、モバイルノート PC で開発作業にあたることが無謀である、ということがわかります。 規模の大きなプロジェクトの場合、 Entity Framework Core のプロジェクトの数倍から数十倍の規模になることはよくあると言えます。 Visual Studio 2022 が 64bit 化されるとアナウンスされたとき、割と歓迎の声が聞こえていました。 これは、それだけ規模の大きなプロジェクトを扱っている人が多いということなのだと思います。 そういったプロジェクトに触れる機会が多いのであれば、モバイルノート PC では満足いく性能を得られない可能性が高いと言わざるを得ません。

モバイルノート PC のコストパフォーマンス

コストパフォーマンスの面でも、モバイルノート PC は、あまり優れたものではありません。 今回紹介している Surface Laptop 3 のマシンは、定価で税込み約 20 万円ほどでした。 これだけの金額があれば、デスクトップ PC は余裕で超ハイスペックなものを組めてしまいます。 プログラム開発用途であれば、グラフィックボードは「映ればよい」程度のもので問題ありません。 なんなら CPU 内臓の GPU でも全く問題ないと思います。 そう考えると、モバイルノート PC のコストパフォーマンスの悪さは一層際立ちます。 Core i7 11700K を使って、 32 GBメモリ、 1TB SSD(M.2)を前提で組むと、たぶんケースとかケチれば、15 万以内(OS 込み)で組めると思います。 ゲームをしないのであれば、ほとんどの人にとって過剰スペックなマシンで、この値段です。

モバイルノート PC の良いところ

モバイルノート PC の良さは、持ち運びできる軽さと、事務作業などの軽い作業を問題なくこなせる性能を両立しているところにあります。 デザイン面もよく、多くのものが洗練された素晴らしいデザインをしています*1。 要するに、持ち運んでちょっとした仕事をすることに特化した PC であって、 IT エンジニアがガンガン開発を行うことを想定したものではないのです。 もちろんちょっとした開発なら余裕でこなせますが、規模が大きくなると問題になることが、今回の検証でも明らかと言えます。 どの部分に価値を置くかは人それぞれだと思いますが、性能を求めるのであれば、モバイルノート PC を選択することはあまり良い選択とは言えません。

しかし、処理性能に対する消費電力という意味では、モバイルノート PC の能力は桁違いに高いと言えます。 今回使用した Core i7 1065G7 の TDP はわずか 15W です。 デスクトップ用の CPU は 65W~ であり、ワットパフォーマンスではモバイルノート PC の圧勝です。 7 ~ 8 年くらい前のデスクトップ PC を持ち運んでいる、という感覚でよいのかもしれません。

まとめ

今回はモバイルノート PC を .NET 開発で使えるのか、ビルド時間の側面から検証してみました。 プロジェクトの規模が小さいうちは、問題なく .NET 開発に利用できるものの、規模の大きなプロジェクトになると、モバイルノート PC の性能では力不足となる可能性が高いことを確認できました。

私の周りには、こういった無理な環境での開発を強いられている人を割と見かけます。 2 年ほど前見かけたとある開発現場では、この SSD 全盛の時代に、 HDD 搭載の激安ノート PC 使って開発していたんですよね。 当時 5 ~ 6 万くらいで購入できるレベルのものでした。 アプリケーションのビルドに 20 分以上かかっていて、本当にどうやって開発を進めているのか疑問でした。 コストをかけたくない経営側の気持ちはよくわかりますが、これでは余裕で足が出ますよね。 即刻 SSD 搭載の最新機種に切り替えさせましたが。。。

私自身も、こういう環境を経験してきた人の 1 人です。 社会人になってすぐ支給された PC は、起動するのに30分くらいかかる PC でした。 スペックもひどく、まともに開発作業なんてできませんでした*2。 それでも大量の開発をこなさなければならず、当時は本当につらかった記憶しかありません。

経営者やマネジメントの方々、 PC は IT エンジニアにとって最も重要な仕事道具です。 おもちゃのバットで打席に立つ野球選手がいないように、プロにはそれなりのものを与えるべきだと私は思います。 この検証結果をもとに、無理な開発を強いられている人が少しでも減ることを願っています。

次回はこのシリーズの最終回として、メモリの速度に焦点を当ててみようと思います。

*1:某コーヒーショップでドヤるためにはここが重要ですね。笑

*2:当時はノート PC 2 台準備して、 1 台は開発専用、もう 1 台はメーラーと設計書確認用、という人間系のマルチスレッド処理をしていましたね。そのくらい PC の性能が足りていませんでした。

.NET アプリケーションのビルドにはコア数は必要なのか

f:id:masatsuna:20210602200410p:plain

前回まで、 CPU の差異による .NET Core アプリケーションのビルド時間を計測、検証してきました。 ここまでの結果から、「 CPU を新しくハイパワーなものに変更することで、ビルド時間を大きく短縮することができる」ことが明らかになりました。 しかし、前回検証した Core i7 9700K と Ryzen 9 5900X の検証結果から、実は CPU のシングルスレッド性能より、コア数の差がビルド時間に影響を与えるのではないか、という仮説が生まれました。 今回はこの仮説がどの程度正しいのか検証していこうと思います。

環境

今回検証に使用するマシンは以下の通りです。

項目
CPU AMD Ryzen 9 5900X(PBO は有効に設定)
メモリ DDR4 32GB × 2枚(3200MHz)
記憶装置 1TB NVMe M.2 SSD(PCIe 4.0)
マザーボード MSI B550 TOMAHAWK
CPUクーラー Nocture NH-D15

この PC に Hyper-V をインストールし、 Windows 10 の仮想マシンを作成します。 作成するマシンには、 16GB のメモリを割り当てます。 CPU の仮想プロセッサ数を 4 個、 8 個、 12 個とします。

検証内容

検証は .NET 5 のアプリケーションをビルドし、ビルド時間を比較する方法で行います。 対象のソースコードは、 2021 年 5 月初旬に取得したものを使用します。 各アプリケーションは、 NuGet パッケージを参照しているため、事前にパッケージをすべてローカルにダウンロードした状態でビルドを行います。 ローカルファイル内にパッケージがあれば、ダウンロードする処理は行われないため、ネットワークの影響を限りなく無視することができます。

今回検証の対象となるアプリケーションは、以下の 2 つを利用します。

eShopOnWeb

github.com

こちらはマイクロソフト社が開発している .NET Core のリファレンスとなるアプリケーションです。 リファレンスとして使用するもので、プロジェクトの数も 9 つしかありません。

Entity Framework Core

github.com

.NET Core で使用できる代表的な O/R マッパーです。 こちらはそれなりに規模が大きく、 46 プロジェクトで構成されています。

検証手順

eShopOnWeb

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

dotnet restore eShopOnWeb.sln

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

dotnet build eShopOnWeb.sln

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 7 回ずつ実行します。

Entity Framework Core

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

restore.cmd

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

build.cmd

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 7 回ずつ実行します。

検証結果

eShopOnWeb のビルド時間

f:id:masatsuna:20210524204157p:plain

Entity Framework Core のビルド時間

f:id:masatsuna:20210524204208p:plain

結果を見てみましょう。 まずどちらの結果を見ても、プロセッサ数が 4 個の場合、明らかにパフォーマンス劣化が起きています。 プロセッサ数が 8 個以上ある場合、規模が小さいうちはそれほど大きな差はありませんでした。

しかし、規模が大きいプロジェクトでは、プロセッサ数 12 個と 8 個で平均で約 2.5 秒の差がついています。

考察

やはりプロセッサ数が少ないと、ビルド時間に多大な影響が出ることが明らかです。 eShopOnWeb のプロジェクトは、かなり規模の小さなものであると思います。 それであっても、プロセッサ数が 4 個になると性能差が明らかにわかるようになります。 率にすると 5% 程度の差があるようです。

規模が大きくなると、さらにその差は顕著についていきます。 Entity Framework Core のビルド時間は、 4 Core と 8 Core で約 12 秒の差がついています。 率にすると、 27% 程の差がついていることになります。

12 Core まで増やすと、規模の小さなプロジェクトではほとんどビルド時間に差が出なくなっていきます。 規模の大きなプロジェクトでも 6% 程度の差に収まっています。

以上の結果から考えると、最低限プロセッサ数 8 個を確保したほうが、エンジニアとしては幸せになれるということでしょう。

Azure Pipelines のビルドエージェント

ここまでの話は、ビルドマシンとして使う場合にも当てはまります。 例えば Azure Pipelines で利用できる Microsoft Hosted のビルドエージェントは、 Azure の VM でいうところの Standard_DS2_v2*1 を利用しています。 Standard_DS2_v2 は、仮想プロセッサ数 2 つの VM で、ここまでの検証結果から考えると、かなり貧弱なマシンであると言えます。 規模が小さいうちはあまり問題にならないかもしれませんが、プロジェクト数が増えたり、規模が大きくなったりすると、なかなかしんどい結果になることが予想できます。

実際にそれなりに大きな規模のプロジェクトの場合、8 Core くらいの VM を Self Hosted Agent として準備すると、驚くほどビルド時間が短縮できます。 ビルド時間がローカルの開発マシンと比較して長くかかるような現象が見られたら、スケールアップしてコア数を増やすことで、ビルド時間を短縮できる可能性が高いことを示せたと思います。

ただし、 8 Core を超えるマシンを準備しても、ビルド速度という意味ではあまり大きな改善が見込めないかもしれません。 もちろんプロジェクトの構成によっては、並列ビルドが有効に働き、効果が発揮できる可能性も否定できません。 しかし、費用対効果という意味では、 8 Core に軍配が上がる可能性が高くなりそうです。

まとめ

今回は、コア数の差が.NET アプリケーションのビルド時間に影響を与えるかどうか検証してきました。 その結果、コア数はかなり重要な要素であり、コア数が増えた方がビルド時間を短縮できることがわかりました。 また .NET アプリケーションのビルドには、 8 Core くらいのマシンがコストパフォーマンスが良い、という結果が得られました。

今回もなかなか興味深い結果であったと思います。 そして、これまで言われてきた「プログラム開発にはシングルスレッド性能のほうが重要である」という定説は、現在の .NET アプリケーションの開発では、あまり当てはまらないことも確認できました。

ここまで数回にわたって、 .NET アプリケーションのビルドに関するパフォーマンス調査を行ってきました。 次回は、最近開発で利用することの増えてきたモバイルノート PC におけるビルド時間を、 Ryzen 9 5900X と比較してみようと思います。

*1:2021/5/31 現在

Core i7 9700K と Ryzen 9 5900X におけるビルド速度の比較

f:id:masatsuna:20210516194909p:plain

本シリーズのまとめはこちらにあります。

tsuna-can.hateblo.jp

前回は約 6 年前の PC と、現役世代のマシンとで、.NET Core のアプリケーションのビルド速度を比較してきました。 その結果、 PC の最新化によってかなりビルド速度が高速化できることがわかりました。

tsuna-can.hateblo.jp

今回は、比較的新しめの Intel 系 CPU と AMD 系 CPU の比較をしてみようと思います。 例によって CPU 以外にも異なる点が多々ある環境で比較しますので、 CPU の性能差以外にも影響を与えている可能性は十分に考えられます。 できる限り比較する PC のスペックを記載しますので、数値を見る際は、環境の差異にも注意してお読みいただければと思います。

環境

今回比較する 2 台のマシンは以下の通りです。 他にもいろいろ違う点はありますが、検証内容と関係ないものは記載を省いています。

項目 9th Core i7 構成 Zen3 Ryzen 構成
CPU Intel Core i7 9700K AMD Ryzen 9 5900X(PBO は有効に設定)
メモリ DDR4 8GB × 2枚(2666MHz) DDR4 32GB × 2枚(3200MHz)
記憶装置 1TB NVMe M.2 SSD(PCIe 3.0) 1TB NVMe M.2 SSD(PCIe 4.0)
マザーボード ASUS TUF Z390-PLUS GAMING MSI B550 TOMAHAWK
CPUクーラー Nocture NH-U12A Nocture NH-D15

ちなみにこれらの CPU の Cinebench R23 におけるベンチマークを以下に貼っておきます。

項目 Intel Core i7 9700K AMD Ryzen 9 5900X
Multi Core 9,214 21,878
Single Core 1,246 1,622

前回比較した Core i7 4790K から大幅にスペックアップしたCPU です。 Single Core のスコアが約 20 %、 Multi Core のスコアが 約 87 %向上しています。 Core i7 9700K は 8 コア 8 スレッド、 Ryzen 9 5900X は 12 コア 24 スレッドで、 Multi Core に大きな性能差があるのは仕方がない面もあります。 またSingle Core のスコアにも大きな差があります。 Core i7 9700K は 2018 年 4Q に発売、対する Ryzen 9 5900X は 2020年 4Q 発売と、 2 年ほど Ryzen 9 5900X のほうが新しい CPU です。



検証内容

検証は .NET 5 のアプリケーションをビルドし、ビルド時間を比較する方法で行います。 対象のソースコードは、 2021 年 5 月初旬に取得したものを使用します。 前回の記事とは異なる時期に取得したソースコードです。 各アプリケーションは、 NuGet パッケージを参照しているため、事前にパッケージをすべてローカルにダウンロードした状態でビルドを行います。 ローカルファイル内にパッケージがあれば、ダウンロードする処理は行われないため、ネットワークの影響を限りなく無視することができます。

今回検証の対象となるアプリケーションは、以下の 2 つを利用します。

eShopOnWeb

github.com

こちらはマイクロソフト社が開発している .NET Core のリファレンスとなるアプリケーションです。 リファレンスとして使用するもので、プロジェクトの数も 9 つしかありません。

Entity Framework Core

github.com

.NET Core で使用できる代表的な O/R マッパーです。 こちらはそれなりに規模が大きく、 46 プロジェクトで構成されています。

検証手順

eShopOnWeb

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

dotnet restore eShopOnWeb.sln

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

dotnet build eShopOnWeb.sln

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 7 回ずつ実行します。

Entity Framework Core

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

restore.cmd

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

build.cmd

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 7 回ずつ実行します。

検証結果

eShopOnWeb のビルド時間

f:id:masatsuna:20210510204755p:plain

Entity Framework Core のビルド時間

f:id:masatsuna:20210510204810p:plain

結果を見てみましょう。 プロジェクト数の少ない eShopOnWeb の方は、わずかに Ryzen 9 5900X のほうがビルド時間は短いものの、平均時間で 0.12 秒の差しかなく、ほとんど誤差レベルの差しかありません。 それに対して Entity Framework Core の方は、平均時間で約 9.4 秒の差が出ており、圧倒的に Ryzen 9 5900X のほうが早いと言えます。

考察

正直ここまではっきり差がつくとは思ってもいませんでした。 昔からプログラム開発やビルド作業には、シングルスレッドの処理性能が重要であると言われてきました。 しかし、このレベルまで進化した CPU *1では、ベンチマーク上の差はあっても、シングルスレッドの性能差がこれほど大きくビルドの実行時間に対して影響を与えるとは考えられません。

こう考察する理由に、ビルド実行時の CPU 使用率があります。 実はこれらのアプリケーションのビルドを行っているとき、 CPU 使用率はほとんどの時間で 100% になりません。 これはコア単位で見たときも同様で、すべてのコアがほとんどの時間、 70% ~ 90% で推移することが見て取れます。 100% になるのはほんの一瞬の時間しかありません。 シングルスレッドの処理性能が重要なのだとしたら、いくつかのコアが 100% に張り付くような現象が起こるはずです。 しかし、こういった現象は、どちらの CPU も一切確認できませんでした。 そう考えると、今の時代のビルド環境には、シングルスレッドの処理性能を追求することより、コアの数を増やす方が効果的であるという仮説が立てられそうです。

なお規模の小さい eShopOnWeb プロジェクトは、プロジェクト数が少なかったため、コア数の恩恵をあまり受けられなかったことで、時間にそれほど差がつかなかったと考えることができそうです。

まとめ

今回は Intel Core i7 9700K と AMD Ryzen 9 5900X のマシンで、.NET Core のアプリケーションをビルドする時間の比較と考察を行いました。 その結果、昨今のビルド作業では、 CPU のシングルスレッド性能を追求するより、コア数の多い CPU を選択したほうが幸せになれる可能性が高いことを確認しました。 なかなか興味深い結果になったと思います。

次回は、今回浮かび上がった「ビルドにはコア数を増やす方が効果的」という仮説を検証するため、 Ryzen 9 5900X の上に Hyper-V仮想マシンを立ち上げ、割り当てるコアの数を増減させてビルド時間を検証してみます。 果たしてどんな結果になるのか。。。

*1:例えばモバイル用 CPU とデスクトップ CPU など、用途や使われ方が全く異なるものを持ってくれば確実に差は出ると思いますが。

本ブログについて

本ブログをご覧いただき、誠にありがとうございます。 「ツナ缶雑記」(以下、本ブログ)は、ご訪問者が安心してご利用いただけるよう、個人情報の保護に最大限の注意を払います。 本ブログの個人情報保護方針は以下の通りです。

個人情報保護方針(プライバシーポリシー)

ご利用者からご提供頂いた個人・法人のプライベートな情報は、ご利用者の同意がない限り第三者に開示することはありません。 ただし、法律に基づき公的機関から要請があった場合や、法令に特別の規定がある場合、お客様や公衆の生命、健康、資産等に重大な損害が発生する恐れがある場合には、適用外となります。

個人情報保護のため、必要に応じて本方針を改定する場合がございます。 改定が行われた場合、利用者がその内容を知ることができるよう、速やかに本ページに公開し、プライバシーポリシーに記載致します。

アクセス解析ツールについて

本ブログでは、Googleによるアクセス解析ツール「Googleアナリティクス」を使用しています。 このGoogleアナリティクスはデータの収集のためにCookieを使用しています。 このデータは匿名で収集されており、個人を特定するものではありません。 この機能はCookieを無効にすることで収集を拒否することが出来ますので、お使いのブラウザの設定をご確認ください。 この規約に関しての詳細はGoogleアナリティクスサービス利用規約のページやGoogleポリシーと規約ページをご覧ください。

本ブログで掲載する広告を配信する第三者配信事業者及び広告ネットワーク

以下は本ブログで掲載する広告を配信する事業者及び広告ネットワークです。 各社のプライバシーポリシーについては、リンク先のページをご参照下さい。

もしもアフィリエイト

プライバシーポリシー | 株式会社もしも

Amazonアソシエイト・プログラム

Amazonのアソシエイトとして、ツナ缶雑記は適格販売により収入を得ています。

アソシエイト・セントラル - Amazonアソシエイト・プログラム運営規約

楽天アフィリエイト

個人情報保護方針 | 楽天グループ株式会社

Yahoo! Japan アフィリエイトプログラム

Yahoo! JAPANプライバシーセンター

免責事項

本ブログからのリンクやバナーなどで移動したサイトで提供される情報、サービス等について一切の責任を負いません。 また本ブログのコンテンツ・情報について、できる限り正確な情報を提供するように努めておりますが、正確性や安全性を保証するものではありません。 情報が古くなっていることもございます。 本ブログに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。

著作権について

本ブログで掲載している文章や画像などにつきましては、無断転載することを禁止します。

本ブログは著作権や肖像権の侵害を目的としたものではありません。 著作権や肖像権に関して問題がございましたら、お問い合わせフォームよりご連絡ください。 迅速に対応いたします。

運営者

@tsuna_can_se(Twitter

お問い合わせ先

以下のフォームよりお問い合わせください。

forms.gle

改訂履歴

  • 新規作成:2021年 5月10日
  • お問い合わせフォームのリンク先設置:2021年 9月5日

Core i7 4790K と Ryzen 9 5900X におけるビルド速度の比較

f:id:masatsuna:20210508172345p:plain

本シリーズのまとめはこちらにあります。

tsuna-can.hateblo.jp

皆さんが自作 PC を作る目的は何でしょうか。 多くの方が PC ゲームを快適に行うことか、動画作成や画像編集など、クリエイティブな作業を快適に行うことなのではないかと思います。 CPU や GPU の新製品が出ると、ベンチマークソフトやゲーム、動画作成の時間など、様々な検証が行われます。 しかし、 IT エンジニアにとって有益な情報はほとんど出てきません。 IT エンジニアとして知りたいのは、プログラム開発をどの CPU なら快適に行えるのか、ということなんです。 しかし、そういった情報は全くと言っていいほど出てきません(需要がないんでしょうけど)。

今回は今まであまり語られることのなかったプログラム開発の側面から、第 4 世代 Core i7 と、 Ryzen 9 5900X を比較してみようと思います。

環境

今回比較する 2 台のマシンは以下の通りです。 他にもいろいろ違う点はありますが、検証内容と関係ないものは記載を省いています。

項目 4th Core i7 構成 Zen3 Ryzen 構成
CPU Intel Core i7 4790K AMD Ryzen 9 5900X(PBO は有効に設定)
メモリ DDR3 4GB × 4枚 DDR4 32GB × 2枚(3200MHz)
記憶装置 80GB 2.5インチSATA SSD 1TB NVMe M.2 SSD(PCIe 4.0)
マザーボード ASUS MAXIMUS VII HERO MSI B550 TOMAHAWK
CPUクーラー 前マシンから使いまわしの巨大なトップフロー型クーラー(もはや型番とか記憶にない) Nocture NH-D15

ちなみにこれらの CPU の Cinebench R23 におけるベンチマークを以下に貼っておきます。

項目 Intel Core i7 4790K AMD Ryzen 9 5900X
Multi Core 4,936 21,878
Single Core 1,069 1,622

比較するのもアレですが、相当な性能差がある、ということを理解してください。 Core i7 4790K は 2014 年にリリースされた、当時はそれなりに強い CPU でした。 それに対して Ryzen 9 5900X は、 2020 年現在最強に近い性能を持つ CPU です。 どちらも同一世代内では最強に近い性能を持つ CPU です。

検証内容

検証は .NET 5 のアプリケーションをビルドし、ビルド時間を比較する方法で行います。 対象のソースコードは、 2020 年 12 月末に取得したものを使用します。 各アプリケーションは、 NuGet パッケージを参照しているため、事前にパッケージをすべてローカルにダウンロードした状態でビルドを行います。 ローカルファイル内にパッケージがあれば、ダウンロードする処理は行われないため、ネットワークの影響を無視することができます。

今回検証の対象となるアプリケーションは、以下の 2 つを利用します。

eShopOnWeb

github.com

こちらはマイクロソフト社が開発している .NET Core のリファレンスとなるアプリケーションです。 リファレンスとして使用するもので、プロジェクトの数も 9 つしかありません。

Entity Framework Core

github.com

.NET Core で使用できる代表的な O/R マッパーです。 こちらはそれなりに規模が大きく、 46 プロジェクトで構成されています。

検証手順

eShopOnWeb

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

dotnet restore eShopOnWeb.sln

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

dotnet build eShopOnWeb.sln

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 7 回ずつ実行します。

Entity Framework Core

上述のリポジトリからソースコード一式を取得します。 取得したディレクトリをカレントディレクトリに設定し、コマンドプロンプトから以下のコマンドを実行します。

restore.cmd

これで NuGet パッケージをローカルにダウンロードできます。 続いて、 CPU がアイドル状態になり、温度も一定になったことを確認してから、以下のコマンドを実行します。

build.cmd

実行すると、実行時間が最後に表示されるので、その時間を記録します。 この作業を各環境で 5 回ずつ実行します。

検証結果

eShopOnWeb のビルド時間

f:id:masatsuna:20210508164216p:plain

Entity Framework Core のビルド時間

f:id:masatsuna:20210508164237p:plain

結果を見ても明らかなとおり、 PC を最新のものに交換することで、かなりビルド時間の高速化ができたと言えます。 特に Entity Framework Core の方は、ビルド時間が半分以下まで短縮化されています。 ビルドを待っている時間は、 IT エンジニアにとって最もイライラする時間だと思います。 PC を最新化することで、そういった時間を削減することができるのです。

Cinebench R23 のスコアと比較すると、スコアが数倍になったからと言って、処理速度が数倍になる、ということではないことがわかります。 しかし、スコアが大きく上がっていれば、如実に実行時間として表れることは間違いなく言えそうです。

考察

ビルド時の PC のリソース消費を見ていると、ほとんどが CPU の処理時間でした。 ディスク IO など、 CPU とは異なる箇所がボトルネックになるかなーと想像していたのですが、 CPU のほうがボトルネックになるようです。 なお今回のマシンはメモリの速度も大きく異なるため、その性能差が結果に大きな影響を与えた可能性も考えられます。

今回検証したマシンは、世代も全く違いますし、メモリの速度も大幅に違います。 CPU の性能差だけで、これだけの差がついたと結論付けることはできません。 そのあたりは十分に注意して結果を見るようにしてください。

まとめ

これらの PC は、 2014 年と、 2020 年、それぞれの時点でそれなりのスペックを誇る PC であると思います。 6 年たってしまうと、相当に時代遅れなものになってしまうことが、改めて証明されたように思います。

今後同様の検証を何回かに分けて行おうと思います。 プログラム開発を行う上で、どういった環境がベストなのか、自分なりにいろいろ検証した結果をまとめていこうと思います。

パーツの紹介

今回の検証で使用した PC パーツは以下から購入可能です。






Visual Studio サブスクリプションに付属する Azure サブスクリプションが勝手に無効にされた(と思った)話

f:id:masatsuna:20210419115058p:plain

本記事において、悪いのは私であってマイクロソフト社が悪いのではありません。 こんな使い方をしてしまった結果、マイクロソフト社まで問い合わせないと謎が解けなかったよ、という私のダメな記録として残しておきます。

何が起きたか

とある月に、私は Visual Studio サブスクリプションに付属している Azure クレジットを使い切ってしまい、月の途中で無効扱いになってしまいました。 Visual Studio サブスクリプションを契約すると、エディションに応じて Azure のクレジットが付与され、その枠内なら無償で使い放題になります。 この枠を突破してしまうと、 Azure サブスクリプションが無効状態になります。

この無効状態を解除するためには、 Azure サブスクリプションにクレジットカード情報を登録して、制限を解除し課金するように設定するか、 Azure サブスクリプションの月の変わり目まで、再度 Azure サブスクリプションが有効化されるのを待つか、の 2 択です。 私は課金したくなかったので、無効のまま Azure サブスクリプションが再度有効化されるのを待っていました。

待望の月の変わり目がやってきて、 Azure サブスクリプションが再度有効になりました。 もともと無効になってしまったのは、 Cosmos DB の検証をしていて、無償で割り当てられた Azure クレジットを使ってしまっていたからでした。 一刻も早くこの状態をもとに戻さないと、また月の途中で無効状態にされてしまう恐れがありました。

年度頭ということもあって、月の変わり目から 1 日、何も作業できずにいたのですが、翌日、再度 Azure サブスクリプションが無効になった、とのメールが。。。 さすがに 1 日で Azure クレジットを使い切るような設定はしていません。 そして Azure ポータルでトータルコストを見ても、無償枠までまだまだ余裕がある状態でした。

無償枠を上限突破してしまって、 Azure サブスクリプションが無効になるケースは何度も遭遇していますが、今回のパターンは初めてで、何が起こっているのか全く分かりませんでした。

Visual Studio サブスクリプションの状態を確認

とりえあず Visual Studio サブスクリプションんがおかしなことになっていないか確認しました。 過去に何度か社内の管理者がオペミスをして、勝手に私の Visual Studio サブスクリプションを削除されたことがありまして、真っ先に疑いました。

ところが登録状態は問題なく、以下のポータルにログインしても問題なく Visual Studio サブスクリプションは認識されています。

https://my.visualstudio.com/

これで Visual Studio サブスクリプションが犯人である説は消えました。

Azure ポータルから問い合わせてみる

課金関連の問い合わせは、 Azure ポータルから無償で行うことができます。 Azure ポータルの以下のメニューから、問い合わせを起票しました。

f:id:masatsuna:20210419111342p:plain

f:id:masatsuna:20210419111458p:plain

ところが、どうも会話がかみ合いません。 サポート窓口の人が言うには、 Azure DevOps が原因だ、と。 具体的に何が問題になっているかは教えてくれなかったのです。 確かに Azure DevOps は使っていますが、課金されるような使い方をしたつもりは一切ありませんでした。

真犯人は。。。

結論から言うとチームメンバーのオペミスが原因でした。 チームで利用している Azure DevOps 組織は、 Visual Studio サブスクリプションの特典で取得した私の Azure サブスクリプションに対して紐づけられていました。 その Azure DevOps 組織には、チーム内のメンバー数名を管理者として登録していました。 その人が、 Azure DevOps のユーザーを登録する際、 Basic レベルのメンバーを 6 名登録してしまい、私の Azure サブスクリプションに対して課金が発生した、というのが真相でした。

Azure DevOps の課金は、 Visual Studio サブスクリプションで与えられる無償の Azure クレジットを支払いに使うことができません。 そのため、 Azure サブスクリプションに対してリアルな課金が発生します。 しかし、 Azure サブスクリプションにクレジットカードが登録されていなかったためリアルな課金ができず、 Azure クレジットが余っているように見えるのに無効扱いにされてしまったのです。

その後、 Azure ポータルからこの月限定でクレジットカード決済できるように設定し、難を逃れました。 この月限定で課金、というのが設定できるのは非常にうれしいですね。

まとめ

私の視点で見ると、突如 Azure サブスクリプションが無効にされたように見えたため、とても混乱したお話でした。 しかも無効にされた理由が自分では全く把握できなかったんですよね。 Azure DevOps のユーザーの登録状況や、ビルドマシンの使用状況など、課金の発生するような使い方をされていないか、随時確認するようにしないとダメですね。 こんなアホなことやらかすのは私くらいでしょうが、ここに供養しておきます。

ある程度の規模の Azure DevOps を運用するなら、リアル課金できる Azure サブスクリプションに Azure DevOps の課金設定を変更しておかないと怖いですね。 手順は以下に記載がありますので参考までにどうぞ。

docs.microsoft.com

この件でマイクロソフトさんからいくつか聞いたので箇条書きで残しておきます。 ここに示すのは 2021 年 4 月に私が聞いた情報です。 将来変わるかもしれませんし、正しくないかもしれません。 あまり鵜吞みにしないようにしてください。

  • 上記の手順に従って Azure サブスクリプションの変更する場合、変更先の Azure サブスクリプションの Azure AD に、 Azure DevOps 上のユーザーを登録する必要があるが、課金先の Azure サブスクリプションの変更を行った後で、そのユーザーを Azure AD から削除しても問題なく課金はされる( Azure ポータル上 Azure DevOps のリソースが存在すれば、そこが課金対象のサブスクリプションになる)
  • 上記の手順をスキップして、マイクロソフト社に、 Azure DevOps の課金対象の Azure サブスクリプションを変更するよう依頼することはできない(必ず上記のオペレーションでユーザーに実施してもらう)
  • 上記の通り変更する場合も、 Azure DevOps の組織を Azure AD と接続する必要はない
  • Azure DevOps が課金できない状態だと、 Azure DevOps も読み取り専用状態にさせられる(と言われたが、実際にはされていなかったため真偽不明)

Azure Pipelines のビルド環境考察(MS Hosted Agent vs Self Hosted Agent)

f:id:masatsuna:20210318022823p:plain

ついに MS Hosted の利用制限が強化される

Azure DevOps のチームから以下の 2 件のブログポストがありました。

devblogs.microsoft.com

devblogs.microsoft.com

要約すれば以下の 2 点が言われています。

  • パブリックなプロジェクトの場合、 Azure Pipelines の MS Hosted Agent 無償利用枠を使いたいならメールせよ
  • プライベートなプロジェクトの場合、 Azure Pipelines の MS Hosted Agent 無償利用枠を原則自動付与するするが、自動付与されない場合はメールせよ

メールの送付先とか、メールに含める内容については元記事を参照してください。

なぜこんな制限が?

無償でできてしまうせいで、いろいろ悪いことを考える輩がいるようです。 雑に言えばタダでコンピューティングリソースを使えてしまうわけで、暗号解析とか仮想通貨のマイニングとか、そういった目的に無償のマシンを使われていると。 確かにこの半年くらい、 MS Hosted Agent のビルドマシンはキュー待ちがすごい増えた印象があって、こういうことだったんだなーと妙に腹落ちしました。

MS Hosted Agent をどう使うか

個人的には、 MS Hosted Agent を大規模開発では使わないようにしています。 たとえ規模が小さかったとしても、ビルド時間が手元で 40 秒以上かかるようなプロジェクトの場合は Self Hosted Agent にしています。 こういったプロジェクトの場合、単体テストの実行まで含めると、私の体感として 1 回のパイプライン実行に余裕で 5 分くらいかかってきます。 この待ち時間が微妙にストレスを与えるんですよね。

MS Hosted Agent のマシンは Standard_DS2_v2 の VM 上に展開されています。 Standard_DS2_v2 は 2 Core 7 GB メモリのマシンなので、大多数の方がローカル開発で使用しているマシンよりだいぶ貧弱です。 そういった環境を他の Azure Pipelines のユーザーと共用します。 また悪意を持っているかは別として、長時間のワークロードを実行されるケースもあります。 結果として、キューに入ったままなかなかパイプラインが実行されなかったり、ビルドパイプラインの実行にローカルマシンでのビルドと比較して長時間要したり、ということが起こるわけです。

Self Hosted Agent を用意するタイミング

同時開発者数が 10 名を超えてきたあたりから、徐々に MS Hosted Agent を使うのがしんどくなっていくように経験上思います。 以下のような兆候が見られたら、 Self Hosted Agent の導入を検討すると良いと思います。

  • ビルドパイプラインの実行待ちが増えて、キューに滞留する
  • ビルド時間が大幅に長くなり、なかなかビルドパイプラインが終わらない

Azure Pipelines は、 MS Hosted Agent のほうができることが少ないので、 MS Hosted Agent から Self Hosted Agent への移行はほとんど問題なく実施できると思います。 Self Hosted Agent の環境構築が若干めんどくさいですけどね。

ただ、公開プロジェクトで、 MS Hosted Agent を並列実行できる環境だと、ほとんど Self Hosted Agent を使うことはないと思います。 この辺は本当に使い方によるかなーという印象です。 ビルドパイプラインの状態をよく見ながら検討するべきかと思います。

Azure VM Scale Set Agent

ほかの選択肢として Azure VM Scale Set を用いた Agent もあります。 私は仕事でもこれを使ったことはありません。 たぶん今後も使うことはほとんどないと思います。

最終的に最強なのは何か

個人的におすすめするのは、適当なデスクトップマシンを購入して、そいつを Self Hosted Agent として登録することです。 VM のほうが良ければそれでもいいのですが、先述の通り、現実的な値段で物理マシンと同等以上の性能を持つ VM を用意するのは無理です。 であるならば、適当な物理マシンを Self Hosted Agent として使ったほうが、安くて性能も出せます。

ビルドマシンはサーバーである必要もありません。 安い Windows 10 や Ubuntu のマシンで良いのです。 MS Hosted Agent に不満が出てきたら、 Self Hosted Agent をお試ししてみてください。 いろいろなものが劇的に改善されると思います*1

安く済ませたいならこういったミニ PC を Self Hosted Agent として構築するのがおすすめです。


特に Deskmini シリーズはデスクトップ用の CPU ( TDP 65w まで) が使えるのが良いところです。 非常に小さいですし、組み立ても簡単ですよ。

Deskmini に組み込める最強 CPU は Core i9 10900 です。


Core i5 10500 でも十分な性能を発揮してくれると思います。 正直この辺はお値段と相談です。


デスクトップ CPU にこだわりがないのであれば、完成品で販売しているタイプのミニ PC もよいと思います。 最近よく見かけるのはレノボのミニ PC です。


モバイル PC 用の CPU を積んでいるので、プロセッサーのパワーは Deskmini と比較すると劣ると思います。 しかし、貧弱な VM よりはよほどましです。

まとめ

今回は MS Hosted Agent と Self Hosted Agent の使い分けについて個人的に思うことを書いてみました。 Azure VM Scale Set Agent はいつ使う日が来るのだろうか。

*1:あまり使わなくなってしまった古いマシンを登録するのが一番良いと思います。エンタープライズの利用の場合、適当なデスクトップマシンをレンタルするのでも良いと思います。

Hyper-V で画面が表示されない場合の確認項目(Windows 10)

f:id:masatsuna:20210314015924p:plain

私自身がはまってしまったので備忘録もかねて書いておきます。

現象

Hyper-V を有効にして、 Windows 10 20H2 の仮想マシンを作成しました。 OS のインストールも完了して、ログインアカウントはホスト OS でも使っている MS アカウントに設定。 そして PIN の設定もして、仮想マシンの起動もできました。 Windows Update を実行し、パッチをあてて再起動したら。。。

f:id:masatsuna:20210314012137p:plain

こんな感じでパスワードの入力画面が出てきません。 現在時刻の表示すら出ていません。 右下の電源アイコンとその左隣のボタンだけ操作できる、そんな感じになってしまいました。

原因

聡明な方はすでにお気づきかと思いますが、原因は PIN の設定をしてしまったことと、 Hyper-V を [拡張セッション] モードで起動してしまったことにあります。 この状態ではログインすらできないので、まずは [拡張セッション] モードを無効にします。

[拡張セッション] の設定は、 [表示] メニュー → [拡張セッション] のチェックを外すことでオフにできます。 この設定をオフにすれば、いつもの時計が表示されるようになります。

f:id:masatsuna:20210314012945p:plain

また通常通り PIN を入力してログインすることができます。

f:id:masatsuna:20210314013242p:plain

拡張セッションを使いたい場合

拡張セッションを使うと、ホスト OS のドライブにアクセスできるようになるので、非常に便利です。 拡張セッションを使いたいのであれば、ゲスト OS 側の設定で、 Windows Hello を無効にしましょう。 PIN を有効にすると Windows Hello が有効になります。 この状態だと拡張セッションが使えません。

ゲスト OS 側で [設定] を開きます。

f:id:masatsuna:20210314013903p:plain

[アカウント] を選択します。

f:id:masatsuna:20210314014030p:plain

[サインイン オプション] のメニューを選択します。 OS インストール時に PIN を設定してしまっている場合、 [Microsoft アカウントWindows Hello サインインを要求する] の項目が以下のようにオンになっていると思いますので、オフに設定します。

f:id:masatsuna:20210314014330p:plain

この状態で、再度 [表示] メニュー → [拡張セッション] のチェックをオンにしてください。 今度は MS アカウントのパスワードを入力するための画面が表示されるはずです。

f:id:masatsuna:20210314014819p:plain

今度は PIN ではなく、 MS アカウントのパスワードを入力してログインしましょう。

なお Windows 11 の場合もほとんど同じ設定ができました。 詳細は以下に記載しています。

tsuna-can.hateblo.jp

.NET Framework ベースのアプリケーションを .NET 5 ベースへと更新サポートするツール(upgrade-assistant)

f:id:masatsuna:20210303121532p:plain

つい先日、 .NET Framework ベースのアプリケーションを .NET 5 に移行するための便利ツールが登場しました。 .NET Blog でも紹介されていました。

devblogs.microsoft.com

今回はこいつを軽く触ってみた感想とか、できること、できないことを軽く整理してみようと思います。 なお今回紹介しているのは、 2020/03/03 時点の最新版に基づく情報です。 本日時点ではプレビュー扱いであるため、今後大幅に変更される可能性もありますので、注意してください。

環境

  • dotnet 5.0.103
  • try-convert 0.7.212201
  • upgrade-assistant 0.2.212405

.NET SDK のインストール

コマンドプロンプトを開いて以下のコマンドを実行します。

dotnet

インストールができていれば dotnet コマンドの使い方が出力されます。 コマンドが見つからない、といったエラーになった場合は、以下のページからインストーラを取得して、導入してください。 導入後は再起動しておいた方が良いです。

dotnet.microsoft.com

try-convert ツールのインストール

以下のコマンドを実行して、 try-convert ツールをインストールします。

dotnet tool install -g try-convert

インストールが正常に完了すると、以下のようなメッセージが出力されます。

次のコマンドを使用してツールを呼び出せます。try-convert
ツール 'try-convert' (バージョン '0.7.212201') が正常にインストールされました。

.NET Upgrade Assistant のインストール

以下のコマンドを実行して、 .NET Upgrade Assistant をインストールします。

dotnet tool install -g upgrade-assistant

インストールが正常に完了すると、以下のようなメッセージが出力されます。

次のコマンドを使用してツールを呼び出せます。upgrade-assistant
ツール 'upgrade-assistant' (バージョン '0.2.212405') が正常にインストールされました。

2020/03/03 現在、どちらのツールもプレビュー版扱いなので、メジャーバージョンは 0 になっていますね。

.NET Upgrade Assistant の実行

ソリューションファイルのあるディレクトリに移動して、以下のコマンドを実行します。

upgrade-assistant <*.sln のファイル名>

実行すると、ソリューションに含まれているプロジェクトの一覧が出力されます。 エントリーポイントに相当するプロジェクトの番号を入力して作業を開始します。

-----------------------------------------------------------------------------------------
- Microsoft .NET Upgrade Assistant v0.2.212405+8e7b4314944e5328780f06f20721a4d6ef9783bb -
-----------------------------------------------------------------------------------------

[09:45:11 INF] MSBuild registered from C:\Program Files\dotnet\sdk\5.0.103\
[09:45:11 INF] Registered 1 extensions:
        Default extension
[09:45:13 INF] Initializing upgrade step Select an entrypoint

Upgrade Steps

1. [Next step] Select an entrypoint
2. Select project to upgrade

Choose a command:
   1. Apply next step (Select an entrypoint)
   2. Skip next step (Select an entrypoint)
   3. See more step details
   4. Configure logging
   5. Exit
> 1
[09:46:58 INF] Applying upgrade step Select an entrypoint
Please select the project you run. We will then analyze the dependencies and identify the recommended order to upgrade projects.
   1. CoreProject
   2. WebProject
   3. WpfProject
> 3
[09:49:06 INF] Upgrade step Select an entrypoint applied successfully
Please press enter to continue...

以降このような形で、出力される選択肢の中から番号を選択して、変換作業を行っていくことになります。 今のところ、以下のような処理が実行できるようです。

1. Back up project
2. Convert project file to SDK style
3. Update TFM
4. Update NuGet packages
5. Add template files
6. Upgrade app config files
    a. Convert Application Settings
    b. Disable unsupported configuration sections
    c. Convert system.web.webPages.razor/pages/namespaces
7. Update C# source
    a. Apply fix for UA0001: ASP.NET Core projects should not reference ASP.NET namespaces
    b. Apply fix for UA0002: HtmlString types should be replaced with Microsoft.AspNetCore.Html.HtmlString
    c. Apply fix for UA0003: ActionResult types should come from the Microsoft.AspNetCore.Mvc namespace
    d. Apply fix for UA0004: Filter types should be used from the Microsoft.AspNetCore.Mvc.Filters namespace
    e. Apply fix for UA0005: Do not use HttpContext.Current
    f. Apply fix for UA0006: HttpContext.DebuggerEnabled should be replaced with System.Diagnostics.Debugger.IsAttached
    g. Apply fix for UA0007: HtmlHelper should be replaced with IHtmlHelper
    h. Apply fix for UA0008: UrlHelper should be replaced with IUrlHelper
    i. Apply fix for UA0009: HelperResult should be replaced with Microsoft.AspNetCore.Mvc.Razor.HelperResult
    j. Apply fix for UA0010: [AllowHtmlAttrubute] should be removed

変換作業が完了したら、アプリケーションコードを手で直して、実行できるように修正していきます。 変換作業が完了しただけの状態だと、コンパイルすら通らない状態になります。 コードの手修正はほぼ必須となります。

できること、できないことがある

このツールを実行すると、ターゲットフレームワーク .NET 5 に設定してくれます。 NuGet パッケージの更新作業もある程度やってくれます。 Program.cs や Startup.cs を生成してくれます。 また Web.config に設定してあった AppSettings の内容を appsettings.json に移してくれます。 他にもいくつか、定型的な変換作業を実施してくれます。 逆に言うと、それ以外のことはできません。 アプリケーションコードがコンパイルできる状態まで更新してくれるわけではありません。 そういう意味で、過度な期待は禁物です。 決して魔法のツールではありません。

このツールは、 .NET Framework のアプリケーションを .NET 5 に持っていくために必要な、最低限の作業をやってくれる印象です。 使いこなすためには、以下のような知識が個人的には必要と思いました。

  • .NET Framework アプリケーションの仕組み
  • もともとのアプリケーションの構造
  • .NET 5 アプリケーションの基本的な仕組み

要するに、わかっている人が使うなら超便利なんですが、わかっていない人が使うとわけわからん、となるように思います。

ASP.NET MVCWPFWindows フォームに対応

公式ドキュメントでは、.NET Framework ベースの ASP.NET MVCWPFWindows フォームアプリケーションを、 .NET 5 ベースに変換できると説明されています。 きっとできることはこれからどんどん増えていくと思います。 今後のアップデートとGAに期待しましょう。

xUnitで単体テストの並列実行をオフにする

f:id:masatsuna:20210303024437p:plain

xUnit を使って C#単体テストを作り、全テストをまとめて実行すると、一部の単体テストが並列実行される様子がわかります。 もう少し正確に言うと、 1 つのテストクラス内のテストは直列実行されますが、異なるテストクラスに配置されているテストは並列実行されます。 このあたりの挙動についてまとめてみようと思います。

環境

テストコレクション

冒頭に述べた挙動は、 xUnit の持つテストコレクションという概念で説明ができます。 テストコレクションは、動画サイトにおける再生リストのようなもので、同一のテストコレクションの中に含まれているテストは、直列実行されるようになっています。 しかし、テストコレクションが異なれば、お互いにテストは並列に実行されるようになっています。

1 つのテストクラス内に含まれるテストメソッドは、すべて同じテストコレクションに含まれます。 特に何も指定しなければ、テストクラス単位でテストコレクションが作成されます。

コードレベルで見ると、以下のように 1 つのテストクラス内にあるテストメソッドは、テストコレクションが同一になるため、順次実行されます。

public class TestClass1
{
    // Test1, Test2 は順次実行(順不同)

    [Fact]
    public void Test1()
    {
        // Do something...
    }

    [Fact]
    public void Test2()
    {
        // Do something...
    }
}

それに対して、以下のようにテストクラスを分割すると、各テストメソッドはテストコレクションが別になるため、並列実行されます。

// Test1, Test2 は並列実行

public class TestClass1
{
    [Fact]
    public void Test1()
    {
        // Do something...
    }
}

public class TestClass2
{
    [Fact]
    public void Test2()
    {
        // Do something...
    }
}

テストを直列実行できるようにする

テストを直列実行するためには、いくつかの方法があります。

テストコレクションをまとめる方法

テストコレクションが 1 つであれば、テストメソッドは直列実行されるようになります。 テストクラスに対して CollectionAttribute を付与することで、テストコレクションを明示的に指定することができます。 CollectionAttribute の引数にテストコレクションの名前を与えることができます。 テストクラスに対して同名のテストコレクションであることをマークすることで、テストコレクションを 1 つにまとめることができます。

[Collection("テストコレクションHoge")]
public class TestClass1
{
    [Fact]
    public void Test1()
    {
        // Do something...
    }
}

[Collection("テストコレクションHoge")]
public class TestClass2
{
    [Fact]
    public void Test2()
    {
        // Do something...
    }
}

このようにテストコレクションをまとめておけば、テストは直列実行されます。

テストクラス単位にテストコレクションが作られないようにする方法

テストクラス単位にテストコレクションが作られてしまう既定の動作を変更することができます。

using Xunit;
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]

このようなコードを追加することで、テストコレクションの単位がアセンブリ単位になります。 こうすることでテストが直列実行されるようになります。

テスト実行のスレッド数を制御する方法

テストが並列実行されるのは、テストランナーが複数のスレッドを起動しているからにすぎません。 なのでスレッドの数を制限することでも、テストが直列実行できます。

using Xunit;
[assembly: CollectionBehavior(MaxParallelThreads = 1)]

この例ではスレッドを 1 つに制限しているので、テストコレクションの単位とは関係なく、テストは直列実行されます。

並列処理を無効に設定する方法

そもそもテストの並列実行機能をオフに設定することもできます。

using Xunit;
[assembly: CollectionBehavior(DisableTestParallelization = true)]

まとめ

xUnit のテスト並列実行についてまとめました。 特にデータベースに依存するようなテストを xUnit で書いていると、こういった問題にぶち当たるかと思います*1。 安易に並列実行をオフにすることは推奨しませんが、いざというケースでは使えるのではないでしょうか。

参考資料

xunit.net

*1:そんなテストコードを xUnit で書くな、という話はもちろんありますけどね。