23
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

C# + LINQ の速度比較(.NET Framework 4.7 ~ .NET 10)

Last updated at Posted at 2024-08-28

はじめに

本記事は、これまでの (.NET Framework 4.7 ~ .NET 8) の内容に .NET 10 を加え、改めてベンチマークをとり、編集しました

C# を使った開発では LINQ を多用します。アプリケーションのパフォーマンスについて議論する際はこの LINQ の影響が大きいと考え、フレームワークによりどれほど違いがあるのかを確かめてみました。

測定したメソッド

下記の5件の実行時間を測定しました。

  1. Select
  2. Where
  3. OrderBy
  4. Max
  5. Sum

比較したフレームワーク

下記6件のフレームワークを比較しました。

.NET Framework

リリース サポート終了
4.7.2 2018-04-30 ???
4.8 2019-04-18 ???
4.8.1 2022-08-09 ???

.NET

リリース サポート終了
8.0.22 (LTS) 2025-11-11 2026-11-10
9.0.11 2025-11-11 2026-11-10
10.0.0 (LTS) 2025-11-11 2028-11-14

.NET Framework は 4.8.x が最後のリリースです。また、このサポート終了は Windows Server 2022 のサポート期限を考慮すると「2031-10-14 より後」と考えられているようです。

対して .NET 10 のサポート終了は「2028-11-14」と .NET Framework 4.8 より早くサポート終了を迎えますが、後続として LTS 版である .NET 12 のリリースが控えています。
.NET 12 は 2027年11月にリリースされる予定であり、リリースから 3年間のサポートが予定されています。

検証環境

下記スペックの PC にて検証しました。

  • CPU: Intel(R) Core(TM) Ultra 7 155H (3.80 GHz)
  • RAM: 32.0 GB
  • OS: Windows 11 Pro (25H2 / 26200.7171)

検証方法

Microsoft Visual Studio Professional 2026 Version 18.0.0 にて検証ソースを Release ビルドして実行しました。

検証結果

.NET 10 が比較したメソッドの全てにおいて速いです。
特に Sum メソッドが圧倒的に高速化 されています。
※ Excel 帳票を出力する際に Sum メソッドを多用する私にはとても嬉しい結果です 😍

下記の表は .NET Framework 4.8.1 での結果を 1.000 とした場合の値です

所要時間

4.7.2 4.8 4.8.1
Select 1.094 0.970 1.000
Where 1.046 1.105 1.000
OrderBy 1.033 1.091 1.000
Max 1.020 1.091 1.000
Sum 1.037 1.082 1.000
8.0.22 9.0.11 10.0.0
0.231 0.212 0.191
0.539 0.426 0.512
0.535 0.498 0.477
0.676 0.596 0.216
0.780 0.699 0.135

メモリ使用量

4.7.2 4.8 4.8.1
Select 1.000 1.000 1.000
Where 1.000 1.000 1.000
OrderBy 1.000 1.000 1.000
Max 1.000 1.000 1.000
Sum 1.000 1.000 1.000
8.0.22 9.0.11 10.0.0
0.958 0.958 0.958
1.997 0.610 0.610
0.955 0.955 0.955
0.833 0.833 0.833
0.833 0.833 -

検証ソース

下記のコードにて BenchmarkDotNet を利用し、処理の所要時間とメモリ使用量を出力しました。

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqBenchmark
{
	internal class Program
	{
		/// <summary>
		/// エントリポイント
		/// </summary>
		private static void Main()
		{
			// ベンチマークスタート
			BenchmarkRunner.Run<LinqOperation>();
			Console.ReadLine();
		}
	}

	[MemoryDiagnoser]
	public class LinqOperation
	{
		/// <summary>リストの要素数</summary>
		private const int LEN = 10000;

		/// <summary>リスト</summary>
		private readonly List<Entity> _entities = new List<Entity>();

		/// <summary>
		/// コンストラクタ
		/// </summary>
		public LinqOperation()
		{
			// リストを初期化
			for (var i = 0; i < LEN; i++) _entities.Add(new Entity(i));

			// シャッフル
			_entities = _entities.OrderBy(n => n.Guid).ToList();
		}

		[Benchmark]
		public void Select()
		{
			var array = _entities.Select(n => n.No.ToString()).ToArray();
			if (array.Length != LEN) throw new Exception();
		}

		[Benchmark]
		public void Where()
		{
			var list = _entities.Where(n => n.No % 2 == 0).ToList();
			if (list.Count != LEN / 2) throw new Exception();
		}

		[Benchmark]
		public void OrderBy()
		{
			var list = _entities.OrderBy(n => n.No).ToList();
			if (list[0].No != 1 || list[LEN - 1].No != LEN) throw new Exception();
		}

		[Benchmark]
		public void Max()
		{
			var max = _entities.Max(n => n.No);
			if (max != LEN) throw new Exception();
		}

		[Benchmark]
		public void Sum()
		{
			long sum = _entities.Sum(n => n.No);
			if (sum != 50005000) throw new Exception();
		}
	}

	internal class Entity
	{
		public int No { get; set; }
		public string Guid { get; set; }

		public Entity(int index)
		{
			No = index + 1;
			Guid = System.Guid.NewGuid().ToString();
		}
	}
}

測定データ

.NET Framework 4.7.2

Method Mean Allocated
Select 486.46 us 407,658 B
Where 127.37 us 65,810 B
OrderBy 1,338.41 us 251,624 B
Max 67.51 us 48 B
Sum 62.69 us 48 B

.NET Framework 4.8

Method Mean Allocated
Select 431.27 us 407,657 B
Where 134.59 us 65,810 B
OrderBy 1,413.95 us 251,624 B
Max 72.23 us 48 B
Sum 65.40 us 48 B

.NET Framework 4.8.1

Method Mean Allocated
Select 444.65 us 407,657 B
Where 121.79 us 65,810 B
OrderBy 1,295.86 us 251,624 B
Max 66.21 us 48 B
Sum 60.46 us 48 B

.NET 8.0.22

Method Mean Allocated
Select 102.81 us 390,528 B
Where 65.59 us 131,432 B
OrderBy 692.68 us 240,304 B
Max 44.79 us 40 B
Sum 47.17 us 40 B

.NET 9.0.11

Method Mean Allocated
Select 94.17 us 390,528 B
Where 51.85 us 40,128 B
OrderBy 644.80 us 240,336 B
Max 39.45 us 40 B
Sum 42.26 us 40 B

.NET 10.0.0

Method Mean Allocated
Select 85.067 us 390,528 B
Where 62.362 us 40,128 B
OrderBy 617.540 us 240,336 B
Max 14.333 us 40 B
Sum 8.180 us -

凡例

  • Mean: Arithmetic mean of all measurements
  • Error: Half of 99.9% confidence interval
  • StdDev: Standard deviation of all measurements
  • Allocated: Allocated memory per single operation (managed only, inclusive, 1KB = 1,024B)
  • 1 us: 1 Microsecond (0.000001 sec)

おわりに

検証した LINQ メソッドの全てにおいて速くメモリ使用量も少なく済む結果となった .NET 10 は、後続の .NET 11、.NET 12 にてさらなる速度改善が期待されています。パフォーマンス面では、今後の開発において .NET Framework 系を選択する理由はないように思います。

23
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?