我用List <string>命中了OutOfMemoryException - 这是限制还是我遗漏了什么?</string>

时间:2012-11-22 22:45:14

标签: c# list memory out-of-memory

如果有机会重写,我会,但无论如何,代码如下:

List<string> foobar;

然后我们将一堆字符串添加到foobar。

在count = 16777216时,我们达到内存不足限制。

我的理解是每个字符串的大小不同。确实在查看数据(不是我的数据),大多数是2或3个字符。

what is the max limit of data into list in c#?表示最大限制为:

  

当前可以存储的最大元素数   从理论上讲,List的实现是Int32.MaxValue - just   超过20亿。

然而:

  

在CLR的当前Microsoft实现中,有2GB   最大对象大小限制。 (有可能是其他实现,   例如Mono,没有这个限制。)

在我的例子中,我有,1600万个结果*几个字节?任务管理器显示正在使用的演出,但我有8演出的RAM。

16777216(2 ^ 24)似乎是一个相当具体的价值 - 可疑地像一个限制,但我无法找到任何文件a)支持或b)找到解决方法?

任何帮助都将不胜感激。


一些代码:

List<string> returnList = new List<string>();
SqlDataReader dr; //  executes a read on a database, have removed that part as that bit works fine

  if (dr.HasRows)
  {
      while (dr.Read())
      {
          returnList.Add(dr.GetString(0).Trim());
      }
  }

这是简化形式,我现在有一些尝试/捕获OOM异常,但这是给我悲伤的实际代码。

3 个答案:

答案 0 :(得分:8)

如果您尝试在64位环境中使用非常大的列表,则需要在应用程序配置中启用大型对象。

http://msdn.microsoft.com/en-us/library/hh285054.aspx

OOM可能是由于Lists / ArrayLists分配内存的方式,我相信每次达到它们的边界时,它们都会尝试将内存加倍。该列表不能从2 ^ 24加倍。理论上,您可以通过预先指定大小来最大化列表大小。 (即2GB)

答案 1 :(得分:1)

我已经发布了我在这里所做的一切,值得一试。 再一步是:

  1. 使用存储过程
  2. 在每个迭代查询数据部分
  3. 转移他们
  4. 转到下一部分

    List<string> returnList;
    int index = 0;
    SqlCommand cmd = new SqlCommand("ExampleStoredProc", conn);
    cmd.CommandType = CommandType.StoredProcedure;
    while (true)
    {
        cmd.Parameters.Add(
            new SqlParameter("@index", index));
        SqlDataReader dr = cmd.ExecuteReader();
        if (dr.HasRows)
        {
            returnList = new List<string>();
            returnList.Add(dr.GetString(0).Trim());
            //transfer data here
        }
        else
        {
            break;
        }
        index++;
    }
    
  5. 并且存储过程应该是这样的:

    CREATE PROCEDURE ExampleStoredProc
        @index INT
    AS
    BEGIN
        SELECT * 
        FROM  veryBigTable
        WHERE Id >= (@index *1000) AND Id < ((@index + 1) * 1000)
    END
    GO
    

    无论你有多少记录,我都会工作,只要你拥有的数据越多,完成的时间就越长。

答案 2 :(得分:1)

如果手动设置正确的列表大小时,它甚至会少于2 ^ 24,那么这可能是在正确的轨道上。而不是达到1600万,然后尝试将列表的大小加倍,它将使列表变得非常大,从而开始并且早先耗尽内存。

这解释了为什么你得到一个圆数 - 它达到2 ^ 24然后试图增加大小,这导致它使用太多的内存。

听起来像是某种'自然'对象大小限制,而不是列表实现中的那种。