2013年03月03日

DataTableのMax行件数は4,194,304件?

うちの環境でやると、同じ件数でOutOfMemoryExceptionが発生する。
約400万件ってなんの制限?
これが40億ちょっとなら、32bit制限で納得なんだけれど。
#テストソースは下に掲載します。

[テスト環境]
・VM(WinXP 32bit) Memory:4GB
・HostOS(Win7の64bit) Memory:12GB

[コンパイル環境]
・Visual Studio 2010
・x86ビルド(Win7は64bitコンパイルも別途試した)
・.Net Framework4 CP

[実行結果(XP)]
ミリ秒単位の経過時間の合計 = 36364ms
プロセス名   :TestDataTableCon
物理メモリ使用量:1514212KByte
仮想メモリ使用量:1856132KByte
i=4194304(件数)

x86ビルドだと、XPでもWin7でも同じ件数で落ちる。
NewRow()したところで落ちている。
同じPC上とはいえ、別OS上で同じところで落ちるなら、言語仕様(正確にはフレームワークの仕様)だよね?
う〜ん、なんだこれ?

◆64bitで動作した時は?
ちなみに、Win7上で64bitコンパイルしたものを動かすと、1500万件までは確認したけど、VMとこのプログラムでメモリを食いつくしたので、そこでやめました。

もともとDataGrid上で動作させるプログラム(手動ページング)が一定件数で落ちるのをなんでか調べていたんだけれど、それ以前の話だった orz
意味不明だ。。。

[テストプログラム]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Diagnostics;
using System.Threading;

namespace TestDataTableCon
{
class Program
{
static void Main(string[] args)
{
int i = 0;
Stopwatch sw = new Stopwatch();
sw.Start();

try
{

DataTable tbl = new DataTable("TEST");
tbl.Columns.Add("A", typeof(int));
tbl.Columns.Add("B", typeof(string));
tbl.Columns.Add("C", typeof(string));
tbl.Columns.Add("D", typeof(string));
tbl.Columns.Add("E", typeof(string));
tbl.Columns.Add("F", typeof(string));
tbl.Columns.Add("G", typeof(string));

for (i = 0; i < 100000000; i++)
{
if (1 == (i % 1000))
{
Console.WriteLine("i=" + i.ToString());
}

DataRow row = tbl.NewRow();
row["A"] = i;
row["B"] = "B" + i.ToString("000000000");
row["C"] = "C" + i.ToString("000000000");
row["D"] = "D" + i.ToString("000000000");
row["E"] = "E" + i.ToString("000000000");
row["F"] = "F" + i.ToString("000000000");
row["G"] = "G" + i.ToString("000000000");
tbl.Rows.Add(row);
}

Console.WriteLine(tbl.Rows.Count.ToString() + "行");

Console.WriteLine("正常終了");
}
catch(Exception ex)
{
Console.WriteLine(ex.Message + ex.StackTrace);
}

sw.Stop();
Console.WriteLine("ミリ秒単位の経過時間の合計 = {0}ms", sw.ElapsedMilliseconds);

// プロセス情報の表示
System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();currentProcess.Refresh();
String text = "プロセス名   :" + currentProcess.ProcessName + "\n" + "物理メモリ使用量:" + (currentProcess.WorkingSet64/1024) + "KByte\n" + "仮想メモリ使用量:" + (currentProcess.VirtualMemorySize64/1024) + "KByte";
Console.WriteLine(text);

Console.WriteLine("i=" + i.ToString());
Console.ReadKey();
}
}
}

posted by w033 at 20:39| 東京 ☁| Comment(2) | TrackBack(0) | プログラム | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
制限でありえそうなのはFrameworkのLOH領域(Large Object Heap)の制限とかですかね?
ご存知かと思われますが、GC領域に関してはperformance monitor のGen 0〜2 heep sizeとLarge Object Heap sizeで値が算出できます。

あとDataTable#AcceptChangesやDataRow#BeginEdit/DataRow#EndEditが掲載のコードにないのが気になります。
Posted by laxmi at 2013年04月07日 06:18
上記のソースはページング以前のところでいろいろやっていたら見つけたもので、上記の処理ではDataGridViewとか関係なので、AcceptChangesとか不要だと思います(status=newになるだけ)
また、テーブルに追加前のDataRowならイベント等とも関係ないため、BeginEdit等も関係ないですよね?
つんでるメモリいっぱいまで読み込んで落ちてくれれば、とりあえず納得なんですが。
Posted by 管理人 at 2013年04月09日 22:50
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

この記事へのトラックバックURL
http://blog.seesaa.jp/tb/341752172

この記事へのトラックバック