お久しぶりです、エンジニアのMasashiです。
今回は文字列分割を行う際の速度について検証を行ってみます。
様々な場面で使用される文字列分割ですが、
普段はStringクラスのSplitメソッドを使用して分割を行うのが一般的だと思います。
C#の速度検証を行うにあたりいろいろ調べていたところ文字列分割にはRegexクラスのSplitメソッドがあることも知り、
速度面では違いがあるのか気になり調査してみました。
測定までの流れ
今回測定を行うのは、テキストファイルに書き込まれているカンマ区切りの数字を
カンマで分割し配列に格納するまでに要した時間になっています。
比較対象としてString.Splitを使用した場合とRegex.Splitを使用した場合の2つで速度を検証しています。
測定環境
- Visual Studio 2015
対象データ
- テキストに書き込む数値の数:100,000
- テキストに書き込む数値の内容:0~99,999までの乱数
- 区切り文字:「,」
測定対象
- String.Splitを使用
- Regex.Splitを使用
テストコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
using System; using System.Diagnostics; using System.IO; using System.Text; using System.Text.RegularExpressions; namespace DataSplitSpeed { internal class Program { // 乱数:最大値 private const int MaxValue = 100000; // データ数 private const int DataCount = 100000; //読み込み先のテキストファイル private const string FilePath = @"C:\test\test.txt"; private static void Main() { CreateTestData(); var unsplitData = GetTestData(); for (var i = 0; i < 10; i++) { Console.WriteLine("----------------"); StringSplit(unsplitData); RegexSplit(unsplitData); Console.WriteLine("----------------"); } Console.WriteLine("続行するには何かキーを押してください:"); Console.ReadKey(); } // String.Splitを使用して文字列分割 private static void StringSplit(string unsplitData) { var stopwatch = new Stopwatch(); stopwatch.Start(); var splittedData = unsplitData.Split(','); stopwatch.Stop(); Console.WriteLine("計測時間【String.Split】: " + stopwatch.Elapsed.TotalMilliseconds + "ms"); } // Regex.Splitを使用して文字列分割 private static void RegexSplit(string unsplitData) { var stopwatch = new Stopwatch(); stopwatch.Start(); var splittedData = Regex.Split(unsplitData, ","); stopwatch.Stop(); Console.WriteLine("計測時間【Regex.Split】: " + stopwatch.Elapsed.TotalMilliseconds + "ms"); } // テキストファイルからデータの取得 private static string GetTestData() { return File.ReadAllText(FilePath, Encoding.GetEncoding("shift_jis")); } // カンマ区切りの数字データをテキストファイルに書き込む private static void CreateTestData() { var r = new Random(); var sb = new StringBuilder(); for (var i = 1; i <= DataCount; i++) { // 乱数を結合 sb.Append(r.Next(0, MaxValue)); if (i != DataCount) { sb.Append(","); } } //ファイル書き込み File.WriteAllText(FilePath, sb.ToString(), Encoding.GetEncoding("shift_jis")); } } } |
文字列分割の測定結果
10回試行した結果の平均値が下記になっています。小数点以下は四捨五入しています。
計測項目 | 計測時間(ms) |
---|---|
String.Splitを使用 | 12 |
Regex.Splitを使用 | 70 |
上記の結果を比較してみるとString.Splitがよく使用されている理由がわかるような結果となりました。
Regex.Splitの方もデータ件数から見ると遅いというわけではないですが、String.Splitが圧倒的な差を見せる形になりました。
5倍以上の速度差が生まれていますので、Regex.Splitを使っている既存コードがある場合は、
String.Splitは.NET Framework 2.0から使用が可能なため、String.Splitに置き換える作業を行っていくべきだと思います。
例外として、Regexクラスは正規表現を使用した際によく使用されるため、
正規表現を利用しているソースコードの場合は置き換えを行わないまたは、
正規表現が行われる前後で分割をStringクラスを使用して行うのがパフォーマンス的にはいいと考えられます。
まとめ
文字列分割の速度比較では、圧倒的にString.Splitが早い結果になりました。
Regex.Splitについては使用しているところを見たことがなかったので、遅いから使われないのではないかと考えていましたが、
考えていたとおりの結果となりました。
文字列分割の際は、String.Splitを使う形で速度面では間違いないと思います。
Regexクラスは正規表現等が絡んでいる場合に使用を検討してみてはいかがでしょうか?
この記事が少しでも皆さんのお役に立てば幸いです。