.net column
.NET開発者のためのブログメディア

データ抽出の処理速度

C#の高速化テクニックを伝授します!

2020年08月25日
SE
C#の実行を高速化する方法を教えていただけませんか。
PM
C#のプログラミングでは効率の良いコードを記述して高速化することができます。

C#の高速化とは

今の時代の開発環境は自動的に最適化してくれるので、高速化はあまり考慮する必要が無いと言われます。それでも全く気を付けないのと、高速化を意識するのとでは動作速度にかなり差が出てきます。

今回はC#のプログラミングにおける高速化のテクニックを紹介します。是非これを読んで効率の良いコードを記述してください。

クラスと構造体

C#の高速化と言われて真っ先に上がるのが構造体の使用の推奨です。以下のC#サンプルをご覧ください。

public class TestC
{
public int val;
}
public struct TestS
{
public int val;
}

public static void Main()
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();

for (int i = 0; i < 1000000; i++)
{
TestC c = new TestC();
c.val = 100;
TestMethodC(c);
}

stopWatch.Stop();

Console.WriteLine(stopWatch.ElapsedMilliseconds + “ミリ秒”);
}

public static int TestMethodC(TestC c)
{
return c.val;
}
public static int TestMethodS(TestS s)
{
return s.val;
}

クラスと構造体の実行速度を比較する

上のサンプルは、クラスを生成してメンバフィールドに100を入れてそれを他のメソッドに渡す、という処理を100万回繰り返し、その実行時間の計測をしています。これを実行すると私のPCの環境では60ミリ秒前後という結果になります。

ではforループの中身を以下のように変えてみてください。クラスを構造体に差し替えただけでやることは同じです。

TestS s = new TestS();
s.val = 100;
TestMethodS(s);

クラスと構造体の違い

変更して実行すると、私のPC環境では12ミリ秒前後になります。実に5倍の差がでます。もしstructを使って無かったらと思うと怖いくらいの高速化ですね。なぜこれほどまでに差が出るのでしょうか。

C#の構造体はクラスに比べて継承が出来ないなど、一部の機能がありません。そして最大の違いは、構造体は型が値型であるのに対し、クラスは参照型であることです。この違いが速度の差を生むのです。

クラスは参照渡し、構造体は値渡し

上のC#サンプルではメソッドにクラスや構造体をパラメータとして渡していますが、この時にクラスはインスタンスの参照を渡し、構造体は値を直接渡します。C#では後者の方がずっと速いのです。

では、どんな時も常に構造体の方がずっと速いのでしょうか?実はそうではないのです。ここまでのC#サンプルを以下のように変えてみましょう。

public class TestC
{
public int[] val;
}
public struct TestS
{
public int[] val;
}

public static void Main()
{
var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();

for (int i = 0; i < 1000000; i++)
{
TestC c = new TestC();
c.val = new int[100];
for (int j = 0; j < c.val.Length; j++)
{
c.val[j] = j;
}
TestMethodC(c);
}

stopWatch.Stop();

Console.WriteLine(stopWatch.ElapsedMilliseconds + “ミリ秒”);
}

public static int TestMethodC(TestC c)
{
return c.val[0];
}
public static int TestMethodS(TestS s)
{
return s.val[0];
}

構造体で高速化できるのはデータサイズが小さい時だけ

C#サンプルのクラスと構造体のフィールドを配列にし、int型で100の値を格納して同じ処理をしています。これでクラスと構造体の速さの違いを見てみましょう。結果は、私のPC環境ではどちらも1800ミリ秒前後になります。変わらなくなってしまいました。

このようにクラスと構造体はデータサイズが大きくなると、差が無くなるのです。つまり、構造体で高速化できるのはデータサイズの小さい時だけ、ということになります。高速化できるからと言って何でもかんでもクラスを構造体にするのはやめましょう。

文字列操作にはStringBuilderを使用する

次は文字列操作についてです。以下のC#サンプルを実行してください。

var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();

string str = “a”;
for (int i = 0; i < 100000; i++)
{
str += “b”;
}

stopWatch.Stop();

Console.WriteLine(stopWatch.ElapsedMilliseconds + “ミリ秒”);

+による文字列追加はとても遅い

このサンプルは文字列の追加を10万回繰り返します。実行すると私の環境では6000ミリ秒ちょっとかかってしまいます。+で文字列を追加するのは簡単で便利ですが、処理がとても遅いのです。

ではforループの箇所を以下のように変更しましょう。ソースの先頭には「using System.Text;」を追加してください。

StringBuilder str = new StringBuilder(“a”);
for (int i = 0; i < 100000; i++)
{
str.Append(“b”);
}

StringBuilderを使えば劇的に高速化できる

これを実行すると、私の環境では約4ミリ秒で終わります。実に1500倍の高速化です。+の文字列追加は内部ではStringBuilderクラスのAppendを呼んでいるのですが、最初からそうしてあげるだけでこれほどの高速化ができるのです。

これに近い最適化のテクニックとして、「ボックス化を使わない」というのもあります。以下のC#サンプルを見てください。

var stopWatch = new System.Diagnostics.Stopwatch();
stopWatch.Start();

object num = 0;
for (int i = 0; i < 1000000; i++)
{
num = i;
}

stopWatch.Stop();

Console.WriteLine(stopWatch.ElapsedMilliseconds + “ミリ秒”);

ボックス化は処理が遅い

これを実行すると私のPC環境では30ミリ秒くらいかかります。このサンプルはobject型のnumにint型の値を代入しています。C#にはボックス化という機能があって、抽象的なobject型に数値を代入すると、数値を扱うクラスに変換してくれます。しかしこれはとても遅いのです。

ではこのC#サンプルの、
object num = 0;
を、
Int32 num = 0;
に変えて実行してみましょう。

無駄なnewは避けること

結果は私のPC環境では4ミリ秒くらいになります。約8倍の高速化です。ボックス化の内部処理ではInt32型に変換しているのですが、それをこちらでやってあげればこんなに差が出るのです。

C#に限らずオブジェクト指向言語で遅くなる原因の一つは「無駄にnewすること」です。+による文字列操作もボックス化も、内部でnewをしているため遅くなります。動的なnewを減らし、staticを多用して静的な設計にすると高速なプログラムになります。

ただstaticを多用するとオブジェクト指向的ではない古臭いプログラムになってしまうのも事実で、エンジニアはそういったジレンマを考慮しつつバランスの良い設計を考える必要があります。

SE
いろいろと工夫することで、C#の実行を高速化できるのですね。
PM
紹介したテクニックを活用して、プログラムを記述してください。

常に高速化を意識してC#プログラミングをしよう

C#の最適化のテクニックを紹介しましたが、ご理解頂けましたでしょうか。

コードをシンプルにしてくれる機能は、コンピュータにとっては負担になることがわかったと思います。常に高速化を意識してプログラムを記述するようにしましょう。


.NET分野でのキャリアアップをお考えの方は、現在募集中の求人情報をご覧ください。

また、直接のエントリーも受け付けております。

エントリー(応募フォーム)

Search

Popular

reccomended

Categories

Tags

Jobs