個人的なメモ

Tomohiro Suzuki @hiro128_777 のブログです。Xamarin に関する事を中心に書いています。 Microsoft MVP for Development Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

.NET 6 の Scatter/Gather IO の効果を Visual Studio for Mac 2022 Preview 1 on M1 Mac で試してみましたが、まだ、闇が深かったです(訂正済)

2021/10/05 22:40 検証方法に間違いがあったため(VS for Macデバッグありの実行になっていました)、再度検証し直し記事も訂正しております。ご指摘ありがとうございました。
 
 

はじめに

.NET 6 では FileStream がほぼ完全に書き直されており、速度と信頼性のが高まりました。また、複数のバッファーに対応した(Scatter / Gather IO)新しい API が導入されています。Scatter / Gather IO を使用すると、単一の sys-call で複数のバッファーを渡すことにより、高コストの sys-call の数を減らすことができます。
 
devblogs.microsoft.com
 
 

Visual Studio for Mac 2022 Preview 1 on M1 Mac で試したら...

WindowsLinux でのベンチマーク結果は公式ブログにデータがありましたので、Mac ではどのような結果になるか試してみました。
 
公式ブログの記事内のコードから、サンプルプロジェクトを作成しました。
github.com
 
ベンチマークのライブラリは、BenchmarkDotNet を利用しているようなので、同じように構成しました。
github.com
 
Visual Studio for Mac 2022 Preview 1 で実行した結果ですが...

// * Summary *

BenchmarkDotNet=v0.13.1, OS=macOS Big Sur 11.6 (20G165) [Darwin 20.6.0]
Apple M1 2.40GHz, 1 CPU, 8 logical and 8 physical cores
.NET SDK=6.0.100-rc.1.21463.6
  [Host]     : .NET 6.0.0 (6.0.21.45113), X64 RyuJIT
  DefaultJob : .NET 6.0.0 (6.0.21.45113), X64 RyuJIT


|      Method |     Mean |    Error |   StdDev |
|------------ |----------|----------|----------|
|       Write | 47.92 ms | 1.109 ms | 3.271 ms |
| WriteGather | 48.51 ms | 1.567 ms | 4.621 ms |

 
なんと上記の通り、WriteGather()の方が遅いという結果となりました...
 
 

ベクトル化 IO がうまく機能していない

詳細を解析していないのでなんとも言えないですが、公式ブログでは、Linux ではベクトル化 IO が機能しているとのことでしたが、Mac ではなんらかの理由でうまくベクトル化 IO が機能していない感じです。

一応、.NET 6 と Darwin のソースを調べてみましたが、pwritev() はサポートしているようですが、ベクトル化 IO がうまく機能していない詳細な原因まではわかりませんでした。
 
...と、いったんは思ったのですが、よく見ると、ベンチマーク結果が、X64 となっているので、Rosetta 2 による変換が入っているのが気になります。

ちなみに、意識せず x64 版がインストールされていたのは、dotnet-maui-check でインストールしたからでした。
 
 

Arm64 版 SDK をインストールして再度チャレンジ

というわけで、.NET 6 RC1 SDK をいったん全て削除して、再度 Arm64 版 SDK をインストールして Visual Studio for Mac 2022 Preview 1 で再度試したところ、今度は、無事成功しました。しかも、WriteGather()の方が速く、ベクトル化 IO も効果を発揮しています。

// * Summary *

BenchmarkDotNet=v0.13.1, OS=macOS Big Sur 11.6 (20G165) [Darwin 20.6.0]
Apple M1, 1 CPU, 8 logical and 8 physical cores
.NET SDK=6.0.100-rc.1.21463.6
  [Host]     : .NET 6.0.0 (6.0.21.45113), Arm64 RyuJIT
  DefaultJob : .NET 6.0.0 (6.0.21.45113), Arm64 RyuJIT


|      Method |     Mean |    Error |   StdDev |
|------------ |----------|----------|----------|
|       Write | 45.11 ms | 0.950 ms | 2.772 ms |
| WriteGather | 40.23 ms | 1.304 ms | 3.844 ms |

 
 

今回得た知見

今回の検証で以下のような知見を得ました。

  • M1 Mac .NET 6 の、Scatter/Gather IO は Arm64 版 でしか有効にならない。x64 版では効果がない。
  • M1 Mac .NET 6 SDK の、x64, Arm64 を両方インストールした場合、同じ場所に配置され、後にインストールした方が有効となる。side by side にはならない。
  • M1 Mac .NET 6 SDK の、x64, Arm64 を切り替えたい場合、念のため SDK をいったん削除してから再インストールした方が無難そう。
  • M1 MacVisual Studio for Mac 2022 Preview 1 では Arm64 版 SDK でのデバッグ実行がまだ正常動作しない。x64 版 SDK/Rosetta 2 ならデバッグ実行できる。

 
というわけで、Visual Studio for Mac 2022 の今後のリリースに期待します。