现在我开始研究大量使用缓冲区的典型应用程序..我很惊讶我找不到关于这个主题的明确指南。
我有几个问题。
1)我何时更喜欢在托管内存上使用非托管堆内存中的缓冲区? 我知道.net然后在非托管堆上的对象分配速度更快,并且由于GC开销,对象破坏在.net上要贵得多,所以我认为使用非托管的速度会快一些。什么时候我应该使用fixed {}和Marshal.AllocHGlobal()?
2)据我所知,对于.net中的托管缓冲区和非托管缓冲区使用周引用更有效,如果缓冲区可能在一段时间后重用(基于用户操作),不是吗?
答案 0 :(得分:2)
尝试使用本机“缓冲区”手动管理内存分配对于.NET来说最困难。您不能将托管类型分配到非托管缓冲区,因此它们只能用于结构化数据,在这种情况下,与简单的托管数组(它将连续保留在内存中等)相比,它没什么优势。
通常,尝试管理如何分配和释放对象通常是一种更好的方法,并尝试适当地手动重用它们(当且仅当内存压力对您来说是个问题时)。
至于你的一些具体要点:
我知道.net上的对象分配速度更快,然后在非托管堆上,由于GC开销,对象破坏在.net上要贵得多,所以我认为使用非托管的速度会快一些。
我认为你的假设存在一些缺陷。在分配点,对象分配在.NET中通常更快,因为CLR可能具有已经预先分配的内存,它已经可以使用。对象“破坏”在.NET上也更快,但由于GC的延迟成本可以更高(尽管并非总是如此)。这里有很多因素,主要集中在对象生命周期 - 如果你允许你的对象被提升到Gen1或Gen2,那么事情可能很难跟踪和测量,因为GC压缩成本可能更高。
我什么时候应该使用fixed {}和Marshal.AllocHGlobal()?
一般情况下,您(非常)很少在C#中使用它们。你通常最好不要忘记内存,并允许GC正常工作,这反过来会导致更好的GC启发式整体。
2)据我所知,对于.net中的托管缓冲区和非托管缓冲区使用周引用更有效,如果缓冲区可能在一段时间后重用(基于和用户操作),不是吗?
不一定。重用对象并使它们保持活动时间超过必要时间也存在一些严重的缺点。这可能会保证内存会被提升到Gen2,这可能会让生活变得更糟,而不是更好。
通常,我的建议是信任系统,但要随时测量。如果且仅当您发现真正的问题时,几乎总有办法解决那些特定问题(无需借助非托管或手动管理内存缓冲区)。在处理托管代码库时,使用原始内存应该是绝对的最后手段。