简体   繁体   English

C# 分块数组

[英]C# chunked array

I need to allocate very large arrays of simple structs (1 GB RAM).我需要分配非常大的简单结构数组(1 GB RAM)。 After a few allocations/deallocations the memory becomes fragmented and an OutOfMemory exception is thrown.在几次分配/解除分配之后,内存变得碎片化并抛出 OutOfMemory 异常。

This is under 32 bit.这是 32 位以下。 I'd rather not use 64 bit due to the performance penalty I get - the same application runs 30% slower in 64 bit mode.由于我得到的性能损失,我宁愿不使用 64 位 - 相同的应用程序在 64 位模式下运行速度慢 30%。

Are you aware of some implementations of IList compatible arrays which allocate memory in chunks and not all at once?您是否知道 IList 兼容数组的一些实现,它们以块的形式而不是一次分配内存? That would avoid my memory fragmentation problem.这将避免我的内存碎片问题。

Josh Williams presented a BigArray<T> class on his blog using a chunked array: Josh Williams 在他的博客上展示了一个使用分块数组的BigArray<T>类:

BigArray<T> , getting around the 2GB array size limit BigArray<T> ,绕过 2GB 数组大小限制

You will find more useful information in this related question:您将在此相关问题中找到更多有用的信息:

C# huge size 2-dim arrays C# 巨大的二维数组

A simple ad-hoc fix might be to enable the 3GB switch for your application.一个简单的临时修复可能是为您的应用程序启用 3GB 开关。 Doing so allows your application to use more than the 2GB per-process limit of 32-bit Windows.这样做允许您的应用程序使用超过 32 位 Windows 的每个进程 2GB 的限制。 However, be aware that the maximum object size that the CLR allows is still 2GB.但是,请注意 CLR 允许的最大对象大小仍然是 2GB。 The switch can be enabled using a post-built action for your main executable:可以使用主可执行文件的后期构建操作启用该开关:

call "$(DevEnvDir)..\tools\vsvars32.bat"
editbin.exe /LARGEADDRESSAWARE "$(TargetPath)"

When instantiating an array, .Net tries to find a contiguous part of memory for your array.实例化数组时,.Net 会尝试为数组查找连续的内存部分。 Since total memory limit for a 32-bit app is 2Gb, you can see that it is going to be tough to find such block after several allocations.由于 32 位应用程序的总内存限制为 2Gb,您可以看到在多次分配后很难找到这样的块。

  1. You can try using something like a LinkedList<T> , to avoid the need for contiguous allocation, or restructure your code to make these chunks smaller (although you will not be completely safe this won't happen with a 500Mb array also).您可以尝试使用LinkedList<T>类的东西,以避免需要连续分配,或者重构您的代码以使这些块更小(尽管您不会完全安全,这也不会发生在 500Mb 数组中)。

  2. On the other hand, one solution would be to instantiate this large buffer only once, at the start of your app, and then implement an algorithm which would reuse this same space during you app's lifetime.另一方面,一个解决方案是在应用程序开始时仅实例化这个大缓冲区一次,然后实现一种算法,该算法将在应用程序的生命周期内重用相同的空间。

  3. If you can use IEnumerable instead of IList to pass your data to rest of your program, you would be able to collapse this list using the SelectMany LINQ method.如果您可以使用 IEnumerable 而不是 IList 将数据传递到程序的其余部分,则可以使用SelectMany LINQ 方法折叠此列表。

  4. And at the end, you can simply implement the IList interface in a custom class, and use several smaller arrays under the hood.最后,您可以简单地在自定义类中实现 IList 接口,并在幕后使用几个较小的数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM