C#データ作りすぎでMemoryがフル

このQ&Aのポイント
  • C#で大量のデータを作成する際に、Memoryがフルになってしまう問題が発生しています。
  • 現在、List<HogeData>を使用してデータを作成しているが、その結果Memoryを消費してしまっている。
  • 解決策として、データを他のデータクラスに入れる方法や、DataSetを使用してXML出力してから保存する方法が考えられる。
回答を見る
  • ベストアンサー

C# データ作りすぎでMemoryがフル

現在、以下のデータを大量に作成してMemoryがフルになって困ってます。 List<HogeData> mData = new List <HogeData()> HogeData hogeData = new HogeData(); for(i =0 ; i < 10000000 ; i++) mData.Add(hogeData); そこで、メモリを消費させない方法があれば教えてくれませんか? 今考えてるのは以下です。 1.DataSetなど他のデータクラスに入れる 2.DataSetでXML出力し、一度ファイルなどで保存していく。   使用するときは出力されたファイルを琢次処理していく。

質問者が選んだベストアンサー

  • ベストアンサー
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

>また、1EXEは32bitOS0ですとメモリ最大2GB、64bitOSですとメモリ最大4GBしか使用できないWindows仕様がありますよね。 これ、本当でしょうか? 念のため、ググってみましたが、64bitEXEのアドレス空間の上限は4TBのようです。 https://qiita.com/kimuraya/items/1c9023d2bc27ecaed259 少なくとも4GBということはないと思います。 32ビットの4Gの壁を超える仕組みとしてはメモリマップトファイルがありましたが、64bitEXEでは使わずともよいはずです。 物理メモリを超えた部分はスワップファイルが使われます。 スワップファイルの容量は十分でしょうか。 あと、実際にどのくらいのメモリが必要なのかも一度計算しておいたほうがいいと思います。 あと、 >for(........) ><展開> >} > >単一処理 > >for(........) ><処理> >} つまり、展開をすべて完了してからでないと、「単一処理」が行えない、ということでしょうか? そのあたりの検討をする余地はありそうですが・・・。 検討して、どうしてもとなった場合は、やはりファイルあるいはファイルに準じた処理を行うほうがよさそうです。 ただ、XMLを出力して読み込んでとなると処理時間が非常にかかりそうですのでSqliteあたりを使ってみるのもいいと思います。

mindeyed
質問者

お礼

32ビットの4Gの壁=64bitも同様と勘違いしていました。 また、64bitEXEに変更したところ、エラーとなる状況は回避できそうです。 データの扱いに関しては・・できれば全て展開せずにメモリを圧迫させない形で処理したいのですが設計の見直しが必要ですので検討しようと思います。 非常に助かりました、ありがとうございました!

その他の回答 (4)

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.4

#1です。 展開しつつ琢次処理ではだめなのでしょうか? for(........) <展開> <処理> } という感じで。

mindeyed
質問者

補足

コメント有難うございます。 そこは設計上、下記の流れが必須なもので厳しいです。 for(........) <展開> } 単一処理 for(........) <処理> } 一度、ファイルに落とし込む作業で何とかできないか調査中です。 (データベース化みたいなイメージです。) また、1EXEは32bitOS0ですとメモリ最大2GB、64bitOSですとメモリ最大4GBしか使用できないWindows仕様がありますよね。 これを回避するために、何かしら共通メモリ化みたいなプログラムの手法があった気がします。。もしご存知でしたら教えていただけると助かります。

  • hiodraiu
  • ベストアンサー率15% (447/2818)
回答No.3

このコードだと、ループの前にhogeDataというインスタンスを一つ作って、リストに追加しているだけですから、大量のデータは作られていないですよね。 実際はリストの要素には、それぞれ別のインスタンスってことだと思うのですが、リストにこれだけのデータを格納する必要があるのか、設計自体を見直すというのは無しですか。10000000個ものインスタンスが常にメモリ上に必要な要件ってのは、なかなか珍しいと思います。 別の視点で、HogeDataクラス自体の容量を減らすことは出来ないのですか。

mindeyed
質問者

補足

ご回答ありがとうございます。 設計も見直すのも含めて検討しています。 >10000000個ものインスタンスが常にメモリ上に必要な要件ってのは、な>かなか珍しいと思います。 特殊な処理でして、予め大量データを展開しておかないといけなくそのときにデータをメモリに保存している状況です。(現状8GBがフル) その後、メモリに保存したデータ配列を逐次処理にて実行する事が目的です。 他の方の補足にも書きましたが、C#プログラムでアプリケーションメモリを増やす方法などありましたら教えていただけると助かります。

  • maiko0333
  • ベストアンサー率19% (840/4403)
回答No.2

メモリーを買い足すって手もありますよ。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.1

純粋に琢次処理でよいのなら、Listなんぞ使わずにただのループで処理すればいいだけですよね。 わざわざListにaddするにはそれなりに理由あってのことと思いますが、どんな理由なのでしょうか?それ次第で最適な方法も違ってくると思います。

mindeyed
質問者

補足

ご回答ありがとうございます。 事前に情報を収集しておきたいため、Listなどの配列クラスにデータを蓄積しています。また、データ収集後に逐次処理を実行します。 収集したデータをメモリに蓄積せずに、ファイル化などしていくのも方法化と思っているところです。

関連するQ&A

  • C# DataGridViewにデータを追加したい。

    C# DataGridViewにデータを追加したい。 DataGridViewにレコードを追加したいのですが、Formのロードイベントで以下コードを実行しています。 // テーブルを作成 DataSet dataSet1 = new DataSet("商品マスター"); DataTable dataTable1 = dataSet1.Tables.Add("製品テーブル"); DataColumn dataClumn1 = dataTable1.Columns.Add("ID", typeof(int)); DataColumn dataClumn2 = dataTable1.Columns.Add("名前", typeof(int)); // テーブルにデータを追加 dataTable1.Rows.Add(new Object[] { 1, name1}); dataTable1.Rows.Add(new Object[] { 2, name2}); dataGridView1.DataSource = dataTable1; としています。 Formにボタンを配置し、ボタンクリック時にテキストボックス[txtProName]のデータを レコード追加したいのですが、記入の仕方がわかりません。 まず、 DataSet dataSet1 = new DataSet("商品マスター"); DataTable dataTable1 = dataSet1.Tables.Add("製品テーブル"); をロードイベントメソッドに記入しているのも問題がありそうなのですが、 良く理解できません。 ボタンイベントでデータを挿入する方法等、記入方法のご教授よろしくお願いいたします。 当方、超初心者なので、出来れば、ソースコードもお願いいたします。m(_ _)m

  • XMLからデータセットへ

    こんにちは 初めての質問です。 今XML形の文字列があります。 string strXML = @" <dataset1> <table1> <column1>a</column1> <column1>b</column1> <column1>c</column1> <column1>d</column1> <column1>e</column1> <column1>f</column1> </table1> </dataset1>"; この文字列をXMLファイルとして保存します。 XmlDocument xml = new XmlDocument(); xml.LoadXml(strXML); xml.Save(@"C:\test.xml"); 保存したXMLファイルをデータセットで読み込みます。 DataSet ds = new DataSet(); ds.ReadXml(@"C:\test.xml"); 以上の流れでデータセットの作成はできますが、 一回XMLファイルを保存しないといけません。 何とか保存しないで、文字列から直接データセットを生成する方法はありますか? よろしくお願いします。

    • ベストアンサー
    • XML
  • C#の動的配列について

    こんにちは。今C#でMIDIファイルを解析するプログラムを開発しているのですが、 ファイルからトラック別の音符情報を読み取ってソートするのに結構な時間がかかるのです。 データをソートするのにいちいち別のクラスに全部コピーしてるせいだと思うのですが、データをコピーせずにソートする方法はあるのでしょうか。(もしくは、もっと早い方法) //絶対時間、周波数、フラグ:1=発音 0=消音 ArrayList _time = new ArrayList(); ArrayList _freq = new ArrayList(); ArrayList _flag = new ArrayList(); ~中略~ ~↓本体の一部~ switch (lastStates & 0xF0) { case 0x80: // 音を消す case 0x90: // 音を鳴らす double hz = base_frq * Math.Pow(2.0, (d[addr + 1] - 69) / 12.0); //音の周波数 _freq.Add(hz); _time.Add((long)time);//time=算出した絶対時間 if (d[addr + 1] != 0x0 && (lastStates & 0xF0) == 0x90) _flag.Add(1); else _flag.Add(0); break; ~中略~ musicData[] list = new musicData[_time.Count]; for (int i = 0; i < _time.Count; i++) { list[i] = new musicData((long)_time[i], (int)_freq[i], (int)_flag[i]); } Array.Sort(list);//時間で並べ替え ~中略~ class musicData : IComparable<musicData> { public long time; public int frq; public int flag; public musicData(long time, int frq, int flag) { this.time = time; this.frq = frq; this.flag = flag; } int IComparable<musicData>.CompareTo(musicData other) { return this.time.CompareTo(other.time); } } ソースは以上です。よろしくお願いします。

  • ArrayListに入っているデータで・・・

    addしたデータの位置を知りたいのですが、 たとえばtest2はlist内の何番目にあるか 調べる場合、どうすればわかるでしょうか? よろしくお願いします! List list = new ArrayList(); list.add("test3"); list.add("test1"); list.add("test2");    …    …

    • ベストアンサー
    • Java
  • Datasetの非接続(C#)※初心者

    C#でプログラム開発をしています。 Accessのデータをお客様に配布したくないため、メモリ上にDataSetで取り込めばよいと上司から言われました。 そこでお聞きしたいのですが、下記のようにDataSetでAccessからデータを取り込み、メモリ上に保持はできたのですが、これをデータ接続せずに、再びデータを参照することはできるのでしょうか? // データ元のmdbファイル DataTable dataTable1; DataSet dataSet1 = new DataSet(); OleDbDataAdapter dataAdapter1 = new OleDbDataAdapter( "SQL文", "mdbファイルのパス" ); // データ取得 dataAdapter1.Fill( dataSet1 ); dataTable1 = dataSet1.Tables[0]; お手数ですが、どうか教えてください。

  • delegateの配列

    下記のプログラムのように、number個のタスクがあるとき、parallel個のCPUを使って並列計算したいのですが、以下のプログラムではうまくいきませんでした。 Invokeで実行した後に, actions[i]()が、一時変数のはずのiにアクセスしてしまい、IndexOutOfRangeExceptionが投げられてしまいます。 int parallel = 2; int number = 100; var data = new List<List<int>>(); Action[] actions = new Action[parallel]; for (int i = 0; i < parallel; i++) { data.Add(new List<int>()); actions[i] = () => { for (int b = i; b <= number; b += parallel) data[i].Add(b*b); }; } Parallel.Invoke(actions); 原因はactions[i]の初期化にあるはずで、以下のコードの差し替えるとうまくいきます。 actions[0] = () => { for (int b = 0; b <= number; b += parallel) data[0].Add(b*b); }; actions[1] = () => { for (int b = 1; b <= number; b += parallel) data[1].Add(b*b); }; しかし、たとえばparallel=4などとするといちいちactionsを初期化するのは面倒ですし、処理内容を変えようとすると、4か所すべてを変更しなければならず、ミスを誘発します。 どうすればよいでしょうか。C#に詳しい方、教えてください。

  • ソートについて

    以下のプログラムを実行すると整数のソート結果が "1","12","3"となってしまいます。 整数と文字列を分離させてそれぞれソートさせたいのですが 方法がわかりません。 import java.util.*; import java.io.*; class StrArray{ ArrayList list = new ArrayList(); //最下行に要素を追加 public void add(String data){ list.add(data); } //全ての要素を配列で所得 public String[] getAll(){ String[] all = new String[list.size()]; for(int i=0; i<list.size(); i++){ all[i] = super.get(i); } return all; } public static final int ASC_SORT = 0; public void sort(int mode){ ArrayList al = this.qsort(mode, list); al = list; } //クイックソート public ArrayList qsort(int mode, ArrayList data){ ArrayList result = new ArrayList(); if(data.size()<1){ return new ArrayList(); } String middle = (String)data.get(data.size()/2); ArrayList left = new ArrayList(); ArrayList right = new ArrayList(); for(int i=0; i<data.size(); i++){ if(i != data.size()/2){ if(mode == 0){ if(((String)data.get(i)).compareTo(middle)<=0){ left.add(data.get(i)); } else{ right.add(data.get(i)); } result.addAll(qsort(0, left)); result.add(middle); result.addAll(qsort(0, right)); return result; } return result; } } } } class Sample{ public static void main(String args[]){ StrArray alist = new StrArray(); alist.add("bbb"); alist.add("aaa"); alist.add("ddd"); alist.add("ccc"); alist.add("3"); alist.add("1"); alist.add("12"); alist.sort(0); String[] info = alist.getAll(); for(int i = 0; i < info.length; i++){ System.out.println(info[i]); } } }

  • C♯、PostgreSQLでDB接続用クラスを作りたい。

    開発環境はC♯、DBはPostgreSQLです。 DBアクセス用に共通的に使うクラスを作りたいと思っています。 やりたいことは、 ・接続文字列はapp.configから取得 ・コネクションのプーリング(絶対ではないので出来ない、または メリットがないのであればやらなくても構わない) 以下、途中ですが、書いてみたソースです。 --------ここから using System; using System.Data; using System.Configuration; using System.Collections.Generic; using System.Data.Common; using System.Text; using System.Data.OleDb; namespace InventoryMngProtoType { class DataBaseAccess { //グローバル変数 string connectString; //DB接続用共通クラス //DataReader、DataSet… public DataBaseAccess() { //接続文字列等設定 connectString = System.Configuration.ConfigurationManager.ConnectionStrings["DatabaseConnection"].ConnectionString; OleDbConnection con = new OleDbConnection(connectString); //コネクションオープン if (con.State == ConnectionState.Closed) { con.Open(); } } public DataSet Getdataset(string sql) { System.Data.DataSet ds = default(System.Data.DataSet); //パラメタのSQLを投げ、データを取得、DataSetで返す。 System.Data.OleDb.OleDbDataAdapter MyCommand; MyCommand = new System.Data.OleDb.OleDbDataAdapter(sql, connectString); ds = new System.Data.DataSet(); MyCommand.Fill(ds); return ds; } } } --------ここまで --appconfigの内容 <?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="DatabaseConnection" connectionString="Data Source=localhost" providerName=" PostgreSQL OLE DB " /> </connectionStrings> </configuration> -- まずはSQLをDataSetで返すメソッドから作ろうとしています。 コンストラクタでコネクションを開いておいて、Dispose用の メソッドを用意して、そこで閉じるような作りを考えています。 しかし、 >MyCommand = new System.Data.OleDb.OleDbDataAdapter(sql, connectString); ここで接続文字列が第二引数として必要なようなので、結局、 ここでもコネクションを開くことになるのでしょうか? C♯に慣れていないため、全般、作りについてアドバイス いただけたらと思います。 よろしくお願いします。

  • javascript 連想配列

    初めて連想配列で処理を行っております。いろいろグーグル等で調べましたが、どうしてもできないので、ご教授頂けますでしょうか。 phpからjavascriptにデータを渡し、連想配列化する必要がありまして、以下の通りにやってみました。配列化は自動化したく、for文でこのようにしてみました。phpの大部分は少々長いので省きますが、ざっとこんな感じです。 var place = <?PHP echo $place ?>; //東京、大阪、名古屋 var address = <?PHP echo $add ?>; //東京都、大阪府、名古屋市 var Data = new Array();   for(i=0;i<place.length;i++){ Data[i].push({add1:place[i] , add2:address[i]});   } alert(Data[0]); ------------------------------- 上記の方法ですと、placeとaddressには正しく値はphpから渡されるのですが、肝心なDataはなにも出力されません。エラーもなく、まっさらです。 理想系は、以下の方法の通りにしたいと思っております。 下記はフリーウェアの中身を今回の案件に手直ししたものです。 Data = [{  add1: "東京",  add2: "東京都" }, {  add1: "大阪",  add2: "大阪府" }, {  add1: "名古屋",  add2: "名古屋市" }]; この場合と同じ結果が出力されれば完成なのですが・・・ 例えば、Data[0]をalertすると、「object object」と出力されます。 現在は3件で開発を行っておりますが、今後はどんどん増えていくので、自動化させるためにfor文か、for in文を使ったほうがいいのかな と思っているのですが、力及ばず詰まっております。 どうかお助けください。 よろしくお願い致します。

  • LISTとMAPについて

    以下のように記述されたコードで 他クラスからこのクラスのインスタンスを生成して tempMapのkeyとValueを抜き出したいのですが なにか良い方法ありますでしょうか? 宜しくお願いします。 public class TestListMap { protected List list = null; private Map tempMap = null; public TestListMap(){ list = new ArrayList(); for(int i=0; i < 10; i++ ){ tempMap = new HashMap(); tempMap.put("NO", "00" + i); tempMap.put("TYPE", "AAA" + i); if (i % 2 == 0 | i % 3 == 0) { tempMap.put("FLG", "1"); } else { tempMap.put("FLG", "0"); } list.add(tempMap); } } public List getListMap(){ return list; } }

    • ベストアンサー
    • Java