タイトル | : Re^6: メモリー不足について |
記事No | : 4286 |
投稿日 | : 2006/09/21(Thu) 10:49 |
投稿者 | : 魔界の仮面弁士 |
# 巨大ファイルを用意して検証するほどの余裕が無いので、以下、未検証で書いています。m(_ _)m
≫ヤマ@文系さん
>> stringがcharの配列というかコレクションなので、 アンマネージの話をしているのなら別ですが、少なくともマネージコードにおいて、 .NET の String(≠string) が Char(≠char)配列であるという事は無いのでは。
もちろん、『[String].ToCharArray()』や『New String([Char配列])』を使う事で、 String と Char配列を相互に変換する事は可能ですが、それでも両者は別物であり、 Dim A As Object = New Char() {"X"c} Dim B As Object = TryCast(A, String) のようなコードにおいて、B は Nothing になってしまうことでしょう。
>> charの要素数がintegerのサイズを超えると 「integerのサイズを超える」というのは、具体的にはどういう意味でしょうか?
今回の OutOfMemoryException の件では、200MB のファイルということでしたので、 単純なバイト換算で、 209,715,200 バイトという事ですよね。
一方、Integer型 (System.Int32) のマネージサイズは 32 bit(4 バイト)、 その最大値は 2,147,483,647 ですので「サイズを超え」てはいないと思いますが…。
≫VB2005凡迎徹さん
>>>>>> 読み込むテキストファイルが大きいためにRAMを増やしました。
たとえば下記では、(読込ではなく書込ですが) 198MB を境として OutOfMemoryException が 発生したという報告がありますが、他の開発者の環境では再現させる事ができなかったようです。 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=30540&forum=7
問題点を明らかにするためにも、まずはその例外が、環境依存/データ依存/クラス依存の いずれによって齎されているのか、切り分けが必要かと思います。
1. 別の環境で試してみて、同じエラーになるのか? (環境への依存性の検証。OS の違い、.NET Framework の違いなど。)
2. たとえば、半角空白が並んでいるような単純なデータを読み込む場合にも、 同じサイズで例外が発生するのか? (データ依存性の検証。確実に読めるデータの繰り返しでチェックする。)
3. 例外になるファイルサイズは一定か? それとも数バイト以上の誤差があるのか? (データ依存性の検証。150MB まで OK というなら、次は 175MB で検証するなど、 段々と範囲を狭めていって、現象を起こす分岐点を探す。)
4. 文字列としてではなく、バイナリとして Byte配列に取り込んだ場合はどうか? (クラス依存性の検証。この場合は、メモリ確保に失敗したのか、それとも 文字コード変換時のエラーなのかを判断しています。)
5. Stream からの一括取得ではなく、部分的な取得であれば問題は起きないのか? (もしこれで問題が無いなら、String に対する処理部分を、Stream に対する処理に 書き換えてやれば、問題を解決できる可能性が高まりますよね。)
>> プログラムが複雑になるのと時間がかかると思い、 データサイズが大きい場合には、大量のメモリを一度に確保するという行為は、 長い時間を必要とする可能性があります。(メモリ解放にも時間がかかります)
また、連続した巨大なメモリ領域を確保しようとした場合には、一度に大きな領域を 確保できず、メモリ不足例外となる可能性が高まる点に注意してください。 http://forums.microsoft.com/msdn-ja/ShowPost.aspx?PostID=227022&SiteID=7
元のファイルのデータ形式が不明なので、単純には判断することができませんが、 巨大なデータ(たとえば数十メガバイトを超えるファイル)であるならば、 一括読込はできるかぎり避けて、逐次読込のための仕組みを検討した方が安全でしょう。
# これが Byte配列や String ではなく、Stream や StringBuilder であれば、 # メモリの持ち方が異なるでしょうから、また結果が変わってくるかも知れません。
>>>>>> タスクマネージャーを見ても使用可能領域は十分あります。 >> メモリの使用可能領域が十分あるのに、 確認するとすれば、タスクマネージャーではなく、パフォーマンスモニタですね。 (ファイル名は、「perfmon.msc」です) パフォーマンスモニタの .NET CLR Memory オブジェクトをチェックしてみてください。
|