Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net字典<;int,int>;大约6000000个条目出现内存不足异常_C#_Asp.net_.net_Data Structures - Fatal编程技术网

C# .Net字典<;int,int>;大约6000000个条目出现内存不足异常

C# .Net字典<;int,int>;大约6000000个条目出现内存不足异常,c#,asp.net,.net,data-structures,C#,Asp.net,.net,Data Structures,我正在使用字典存储图像中颜色的频率,其中键是颜色(作为int),值是在图像中找到颜色的次数 当我处理更大/更彩色的图像时,这本词典会变得非常大。我得到一个内存不足异常,大约有6000000个条目。在32位模式下运行时,这是预期容量吗?如果是,我能做些什么吗?还有什么替代方法可以跟踪这些不会耗尽内存的数据 以下是循环位图中像素并将频率保存在字典中的代码,以供参考: 位图b;//=某物 字典计数=新字典(); 系统、绘图、颜色; 对于(int i=0;i

我正在使用
字典
存储图像中颜色的频率,其中键是颜色(作为int),值是在图像中找到颜色的次数

当我处理更大/更彩色的图像时,这本词典会变得非常大。我得到一个内存不足异常,大约有6000000个条目。在32位模式下运行时,这是预期容量吗?如果是,我能做些什么吗?还有什么替代方法可以跟踪这些不会耗尽内存的数据

以下是循环位图中像素并将频率保存在
字典中的代码,以供参考:

位图b;//=某物
字典计数=新字典();
系统、绘图、颜色;
对于(int i=0;i
编辑:如果您想知道什么图像中有这么多不同的颜色:

编辑:我还应该提到,这是在使用.net 4.0的asp.net web应用程序中运行的。因此可能存在额外的内存限制。


Edit:我只是在控制台应用程序中运行了相同的代码,没有问题。此问题仅在ASP.Net中出现。

请尝试改用数组。我怀疑它会耗尽内存。600万int数组元素不是什么大问题。

CLR提供的最大大小限制是2GB

在64位Windows上运行64位托管应用程序时 在操作系统中,您可以创建不超过2 GB的对象 (GB)

您最好使用数组


您还可以检查此更新:

鉴于OP的示例图像,最大项目数似乎超过1600万,即使在实例化字典时,这也太多了。我在这里看到三种选择:

  • 将图像大小调整为可管理的大小,然后从该大小开始操作
  • 尝试转换为具有较少颜色可能性的颜色方案
  • 按照其他人的建议,选择固定大小的数组
前面的答案:问题是你没有为字典分配足够的空间。在某种程度上,当它正在扩展时,您只是耗尽了用于扩展的内存,但不一定是用于新字典

示例:此代码在接近2400万个条目时耗尽内存(在我的机器中,以32位模式运行):

字典计数=新字典();
对于(int i=0;i++)
计数。添加(i,i);
因为在上一次扩展中,它目前正在为已经存在的条目使用空间,并试图为另外数百万个条目分配新空间,这太多了

现在,如果我们最初为(比如)4000万个条目分配空间,那么它运行起来就不会有问题:

Dictionary<int, int> count = new Dictionary<int, int>(40000000);
字典计数=新字典(40000000);
因此,在创建字典时,请尝试指示将有多少条目

发件人:

字典的容量是在需要调整大小之前可以添加到字典中的元素数。当元素添加到字典中时,通过重新分配内部数组,容量会根据需要自动增加。 如果可以估计集合的大小,则在向字典添加元素时,指定初始容量无需执行大量调整大小操作


在32位运行时中,
字典
中最多可包含6170万项。有关更多信息,请参阅

如果您是在32位模式下运行的,那么您的整个应用程序加上ASP.NET的任何位以及所需的底层机器都必须适合进程可用的内存:在32位运行时通常为2GB

顺便说一句,解决你的问题的一个非常古怪的方法(但除非你真的对内存造成了伤害,否则我不会推荐这种方法),如下所示(假设是24位图像):

  • 调用
    LockBits
    获取指向原始图像数据的指针
  • 通过移动每个扫描行的数据以填充前一行的填充,压缩每扫描行的填充。最后是一个3字节值的数组,后跟一堆空白(等于填充)
  • 对图像数据进行排序。也就是说,对3字节值进行排序。您必须编写自定义排序,但也不会太糟
  • 按顺序遍历数组并计算唯一值的数量
  • 分配一个二维数组:
    int[count,2]
    来保存值及其出现次数
  • 再次按顺序遍历数组以计算每个唯一值的出现次数,并填充计数数组

  • 老实说,我不建议使用这种方法。我一想到它就笑了。

    每个字典条目包含两个4字节的整数:总共8字节。8字节*600万个条目只有48MB左右,+/-一些空间用于对象开销、对齐等。内存中有足够的空间用于此。Net为每个进程提供最多2 GB的虚拟地址空间。48MB左右不会引起问题

    我希望这里实际发生的事情与字典如何自动扩展以及垃圾收集器如何处理(或不处理)压缩相关

    首先是自动展开部分。上次我检查时(回到.Net 2.0*),在.Net中的集合倾向于在内部使用数组。他们将在集合构造函数中分配一个大小合理的数组(例如,10个项),一个
    Dictionary<int, int> count = new Dictionary<int, int>();
    for (int i = 0; ; i++)
         count.Add(i, i);
    
    Dictionary<int, int> count = new Dictionary<int, int>(40000000);
    
    var colorCounts = new Dictionary<Color, int>(132651);
    foreach(Color c in GetImagePixels().Select( c=> Color.FromArgb( (c.R/5) * 5, (c.G/5) * 5, (c.B/5) * 5) )
    {
        colorCounts[c] += 1;
    }