System.Drawing.Bitmapからの移行先をくっそまじめに検討した
はじめに
.NET Frameworkと.NET 8.0-windowsで、System.Drawing.Bitmapに依存した実装に十年以上も縛られ続けてきました。
いい加減、真面目に非Windows環境での動作に対応しようという事で、各種画像ライブラリーについて真面目に評価してみました。ただし、あくまで画像ファイルからのデコードと二値化処理に特化した評価になっていますので、かなりニッチな評価だとは思います。
参考になるようであれば、ぜひご利用ください。
評価内容
JPEGと二値のTIFF、WebPの3種類の画像ファイルをデコードし、画像解析用の二値のバイト列へデコードする。
評価結果
先に結論だけ記載すると、つぎのようになりました。
ImageSharpのJPEGデコードアルゴリズムが、System.Drawing.Bitmapと微妙に異なっていました。
目視では分からないレベルだとは思いますが、システム処理している場合に移行する際は注意が必要そうです。
評価ライブラリ
# | ライブラリ | ライセンス | 補足 |
---|---|---|---|
1 | Aspose | 有償 | |
2 | ImageSharp | 有償 | 非商用・小規模商用利用は無償 |
3 | LibTiff.Net | New BSD License | TIFF専用 |
4 | Magick.NET | Apache License 2.0 | |
5 | SkiaSharp | MIT License | |
6 | System.Drawing.Bitmap | - |
※ ImageSharpはv3から大規模商用の場合は有償になりました
※ ImageSharpはJPEGのYCbCrからRGBへの色空間変換アルゴリズムがSystem.Drawing.Bitmapと異なります
上記の2点から、私の用途ではImageSharpはそもそも除外することになりました。
評価環境
# | OS | CPU | CPU Core | Clock | GPU | メモリ |
---|---|---|---|---|---|---|
1 | Windows 11 | AMD Ryzen 9 7950X | 16 | 最大 5.7 GHz | NVIDIA GeForce RTX 4060 Ti | 96GB |
2 | Windows 11 | Intel Core i9-13900H | 8 | 最大 5.4 GHz | NVIDIA GeForce RTX 4070 Laptop | 32GB |
3 | Windows 11 | XEON PLATINUM 8573C | 8 | 最大 3.5 GHz | Intel Xe | 32GB |
4 | Windows Server 2022 | XEON PLATINUM 8573C | 8 | 最大 3.5 GHz | Intel Xe | 32GB |
評価ランタイム
- .NET Framework 4.8.1
- .NET 8.0
評価OS
- Windows Server 2022
- Windows 11
脱WindowsといってるのにWindowsだけですみません。
処理内容
- 画像のデコード
- 大津の二値化による二値化
具体的には下記のベンチマークなどを参照してください。
分析詳細
JPEG
処理速度
まず評価環境#4のWindows Server 2022でベンチマークを取得して比較します。
# | ライブラリ | 処理時間[ms] | 性能比 | Allocated[Bytes] |
---|---|---|---|---|
1 | ImageSharp | 53.087 | 100% | 8,721,641 |
2 | System.Drawing.Bitmap | 65.191 | 81% | 1,348 |
3 | SkiaSharp | 70.241 | 76% | 1,546 |
4 | MagickNet | 101.435 | 52% | 34,790,147 |
5 | Aspose | 167.711 | 32% | 137,316,035 |
性能的にはImageSharpが良いのですが、System.Drawing.Bitmapとの互換性や、ライセンス的に今回は除外する方向で検討したいです(この時点では未決定)。
そのため、移行先の第一候補はSkiaSharpとして後続を検討します。
メモリーのアロケートはSystem.Drawing.BitmapとSkiaSharpが極端に小さいですが、これは.NETの管理外メモリーが利用されているからで、実際にメモリー消費が小さいかどうかはここでは判断できません。
ランタイムとOS
SkiaSharpに限定し、XEONの環境に固定し、ランタイムとOSを変更した場合のベンチマークを分析します。
# | Runtime | OS | 処理時間[ms] | Allocated[Bytes] |
---|---|---|---|---|
1 | .NET 8.0 | Windows Server 2022 | 70.241 | 1,546 |
2 | .NET 8.0 | Windows 11 | 71.609 | 327 |
3 | .NET Framework 4.8.1 | Windows 11 | 72.904 | 2,341 |
.NET Frameworkや、OSがWindows 11の場合でも性能的に大きな差は見られませんでした。
Windows Server 2022上で、.NET Frameworkでなぜかベンチマークが正しく動作しなかったので評価は割愛しています。あまり影響ないでしょうし。
CPUとメモリとGPU
SkiaSharpに限定し、Windows 11 & .NET8.0で、CPUなどを変えた場合のベンチマークを分析します。
# | CPU | Passmark Single | メモリ | GPU | 処理時間[ms] | Allocated[Bytes] | Passmark*処理時間 |
---|---|---|---|---|---|---|---|
1 | AMD Ryzen 9 7950X | 4,272 | 96GB | NVIDIA GeForce RTX 4060 Ti | 53.233 | 1,536 | 227,411 |
2 | Intel Core i9-13900H | 3,798 | 32GB | NVIDIA GeForce RTX 4070 Laptop | 59.796 | 1,540 | 227,105 |
3 | XEON PLATINUM 8573C | 2,474 | 32GB | Intel Xe | 71.609 | 327 | 177,161 |
概ねCPUベンチマークの性能によって決定されることが分かります。XEONの性能が低いのはAzure上のVMのため仮想化の影響でしょうか?
マルチスレッド性能
念のためマルチスレッド性能も見ておきます。著名なライブラリでそうそうマルチスレッド性能が極端に低いということも考えられませんが、念のため。
# | ライブラリ | 処理時間[ms] | 性能比 | Allocated[KB] |
---|---|---|---|---|
1 | ImageSharp | 1,172 | 100% | 851530.56 |
2 | System.Drawing.Bitmap | 1,447 | 81% | 129.79 |
3 | SkiaSharp | 1,636 | 72% | 148.54 |
4 | MagickNet | 2,142 | 55% | 3397526.24 |
5 | Aspose | 3,868 | 30% | 13410745.75 |
傾向は変わらずで、特段問題は見受けられませんね。
TIFF
処理速度
まず評価環境#4のWindows Server 2022でベンチマークを取得して比較します。
# | ライブラリ | 処理時間[ms] | 性能比 | Allocated[Bytes] |
---|---|---|---|---|
1 | LibTiff | 4.871 | 100% | 255,875 |
2 | System.Drawing.Bitmap | 6.364 | 77% | 259 |
3 | ImageSharp | 40.094 | 12% | 10,493,862 |
4 | Aspose | 45.641 | 11% | 72,120,703 |
5 | MagickNet | 67.949 | 7% | 34,790,174 |
LibTiffとSystem.Drawing.Bitmapの性能がとびぬけて高いです。
ImageSharpはのちに出てくるWebPの性能も高いのに、TIFFだけ低めです。これはImageSharpが内部アーキテクチャが二値に直接対応しておらず、一旦RGBAの32bitカラーに展開されてしまうためです。そのためAllocatedも多くなっています。
性能的にはLibTiffが良い感じなので、移行先の第一候補はLibTiffとして後続を検討します。
ランタイムとOS
LibTiffに限定し、XEONの環境に固定し、ランタイムとOSを変更した場合のベンチマークを分析します。
# | Runtime | OS | 処理時間[ms] | Allocated[Bytes] |
---|---|---|---|---|
1 | .NET 8.0 | Windows 11 | 4.63 | 180 |
2 | .NET 8.0 | Windows Server 2022 | 4.87 | 255,875 |
3 | .NET Framework 4.8.1 | Windows 11 | 6.18 | 256,411 |
LibTiffはマネージドライブラリのためか、.NET Frameworkより.NETの性能が高い傾向があります。
#1のAllocatedが少ないのですが・・・
# | CPU | Runtime | OS | 処理時間[ms] | Allocated[Bytes] |
---|---|---|---|---|---|
1 | AMD Ryzen 9 7950X | .NET 8.0 | Windows 11 | 3.446 | 255,874 |
2 | Intel Core i9-13900H | .NET 8.0 | Windows 11 | 3.735 | 255,874 |
3 | XEON PLATINUM 8573C | .NET 8.0 | Windows 11 | 4.633 | 180 |
Windows 11 & .NET8.0でもXEONだけ小さいため、正しく取得できなかった可能性があります。#1, #2あたりが正しいと考えるのが良いかと思います。
CPUとメモリとGPU
LibTiffに限定し、Windows 11 & .NET8.0で、CPUなどを変えた場合のベンチマークを分析します。
# | CPU | Passmark Single | メモリ | GPU | 処理時間[ms] | Allocated[Bytes] | Passmark*処理時間 |
---|---|---|---|---|---|---|---|
1 | AMD Ryzen 9 7950X | 4,272 | 96GB | NVIDIA GeForce RTX 4060 Ti | 3.446 | 255,874 | 14,721 |
2 | Intel Core i9-13900H | 3,798 | 32GB | NVIDIA GeForce RTX 4070 Laptop | 3.735 | 255,874 | 14,186 |
3 | XEON PLATINUM 8573C | 2,474 | 32GB | Intel Xe | 4.633 | 180 | 11,462 |
概ねCPUベンチマークの性能によって決定されることが分かります。XEONの性能が低いのは、JPEGの場合と同じ傾向にあります。
やはりAzure上のCPU性能が、PassmarkのBenchmark結果より低い傾向にあるように思われます。
マルチスレッド性能
# | ライブラリ | 処理時間[ms] | 性能比 | Allocated[KB] |
---|---|---|---|---|
1 | LibTiff | 113 | 100% | 24,991 |
2 | System.Drawing.Bitmap | 170 | 67% | 27 |
3 | ImageSharp | 1,150 | 10% | 1,024,733 |
4 | Aspose | 1,218 | 9% | 7,043,840 |
5 | MagickNet | 1,523 | 7% | 3,397,486 |
System.Drawing.BitmapのAllocatedがさすがに低すぎるのは計測ミスな気がしますが、まぁ気にしません。
特段問題ないでしょう。
WebP
処理速度
WebPに対応しているのは3つのみです。
まず評価環境#4のWindows Server 2022でベンチマークを取得して比較します。
# | ライブラリ | 処理時間[ms] | 性能比 | Allocated[Bytes] |
---|---|---|---|---|
1 | SkiaSharp | 67.962 | 100% | 1,546 |
2 | ImageSharp | 105.665 | 64% | 9,857,987 |
3 | MagickNet | 107.949 | 63% | 34,790,130 |
性能も良いですし、JPEGと統一できるメリットは大きいので、移行先の第一候補はSkiaSharpとして後続を検討します。
ランタイムとOS
SkiaSharpに限定し、XEONの環境に固定し、ランタイムとOSを変更した場合のベンチマークを分析します。
# | Runtime | OS | 処理時間[ms] | Allocated[Bytes] |
---|---|---|---|---|
1 | .NET 8.0 | Windows Server 2022 | 67.962 | 1546 |
2 | .NET 8.0 | Windows 11 | 73.899 | NA |
3 | .NET Framework 4.8.1 | Windows 11 | 75.370 | 2341 |
またWindows 11 & .NET8.0でAllocatedが正しくとれていません。
# | CPU | Runtime | OS | 処理時間[ms] | Allocated[Bytes] |
---|---|---|---|---|---|
1 | AMD Ryzen 9 7950X | .NET 8.0 | Windows 11 | 48.404 | 1,532 |
2 | Intel Core i9-13900H | .NET 8.0 | Windows 11 | 59.879 | 1,536 |
3 | XEON PLATINUM 8573C | .NET 8.0 | Windows 11 | 73.899 | NA |
やはりWindows 11 & .NET8.0でもXEONだけ小さいため、正しく取得できなかった可能性があります。TIFFと同様に、#1, #2あたりが正しいと考えるのが良いかと思います。
CPUとメモリとGPU
SkiaSharpに限定し、Windows 11 & .NET8.0で、CPUなどを変えた場合のベンチマークを分析します。
# | CPU | Passmark Single | メモリ | GPU | 処理時間[ms] | Allocated[Bytes] | Passmark*処理時間 |
---|---|---|---|---|---|---|---|
1 | AMD Ryzen 9 7950X | 4,272 | 96GB | NVIDIA GeForce RTX 4060 Ti | 48.404 | 1,532 | 206,782 |
2 | Intel Core i9-13900H | 3,798 | 32GB | NVIDIA GeForce RTX 4070 Laptop | 59.879 | 1,536 | 227,420 |
3 | XEON PLATINUM 8573C | 2,474 | 32GB | Intel Xe | 73.899 | NA | 182,826 |
ちょっと他と違って#2が#1に比較して高目の数字になっています。
またAzure上のCPU性能が、PassmarkのBenchmark結果より低い傾向にあるのは他と同様です。
ただ特段問題ともいえない範囲に収まっていると思います。
マルチスレッド性能
# | ライブラリ | 処理時間[ms] | 性能比 | Allocated[KB] |
---|---|---|---|---|
1 | SkiaSharp | 1,508 | 100% | 149 |
2 | ImageSharp | 2,170 | 70% | 962,659 |
3 | MagickNet | 2,361 | 64% | 3,397,522 |
SkiaSharpのAllocatedも計測ミスかも?シングル時はちゃんと取れていて、特段高くないのでスルーします。
特段問題ないでしょう。
総評
JPEGとWebPはSkiaSharp、TIFFはLibTiffを利用したいと思います。
性能だけみると、つぎのようになります。
- JPEG: ImageSharp
- TIFF: LibTiff
- WebP: SkiaSharp
ImageSharpであればすべてのフォーマットに対応しますが、TIFFの性能がちょっと微妙です。特にメモリ使用量が気になります。
またImageSharpはJPEGのデコードアルゴリズムが他と違いSystem.Drawing.Bitmapと異なります。目視では問題ないのだと思いますが、私の用途では画像解析に利用するため、System.Drawing.Bitmapと解析結果が変わるのは望ましくないため、選択が難しいです。
TIFFの性能はLibTiffの性能がとびぬけて高いですが、LibTiffを選ぶと必然的に他のフォーマットのために2つ以上のライブラリを使う必要があります。
ImageSharpとSkiaSharpの、JPEGとWebPの性能をもう少し見てみましょう。
# | ライブラリ | JPEG性能比 | WebP性能比 |
---|---|---|---|
1 | ImageSharp | 100% | 64% |
2 | System.Drawing.Bitmap | 81% | 100% |
JPEGのデコードアルゴリズムの相違が問題にならない場合、3つ使い分けるのが最速ではあります。ただどちらかに絞る場合は、扱いフォーマットの多い方の性能で選んでもいいかもしれません。
そういうわけで、つぎのようになりました。
Discussion