Tra*_*rap 11 .net c# memory garbage-collection
这个问题长期困扰着我.我来自一个沉重而长期的C++背景,自从我开始使用C#进行编程并处理垃圾收集时,我总觉得这样的"魔术"会付出代价.
我最近开始在一个用Java(服务器端)编写的大型MMO项目中工作.我的主要任务是优化内存消耗和CPU使用率.每秒发送数十万条消息,同时创建相同数量的对象.经过大量的分析后,我们发现VM垃圾收集器占用了大量的CPU时间(由于常量收集),并决定尝试最小化对象创建,在适用的情况下使用池并重用我们可以做的一切.到目前为止,这被证明是一个非常好的优化.
所以,从我所学到的,拥有一个垃圾收集器很棒,但你不能只是假装它不存在,你仍然需要关注对象创建及其含义(至少在Java和一个大的像这样的应用程序).
那么,.NET也是如此吗?如果是,到什么程度?
我经常写这样的函数:
// Combines two envelopes and the result is stored in a new envelope.
public static Envelope Combine( Envelope a, Envelope b )
{
var envelope = new Envelope( _a.Length, 0, 1, 1 );
Combine( _a, _b, _operation, envelope );
return envelope;
}
// Combines two envelopes and the result is 'written' to the specified envelope
public static void Combine( Envelope a, Envelope b, Envelope result )
{
result.Clear();
...
}
Run Code Online (Sandbox Code Playgroud)
提供第二个功能,以防有人有一个已经制作的信封可以重复使用来存储结果,但我发现这有点奇怪.
当我更喜欢使用类时,我有时会编写结构,因为我知道会有成千上万的实例不断被创建和处理,这对我来说真的很奇怪.
我知道作为.NET开发人员,我不应该担心这类问题,但我对Java和常识的经验告诉我,我应该这样做.
任何有关此事的亮点和想法都会受到赞赏.提前致谢.
是的,.NET也是如此.我们大多数人都忽略了内存管理的细节,但在你的情况下 - 或者在高容量导致内存拥塞的情况下 - 那么需要进行一些优化.
您可以考虑针对您的案例进行的一项优化 - 我一直在考虑撰写一篇文章,实际上是结构和ref实际确定性处理的组合.
由于您来自C++背景,您知道在C++中您可以在堆上实例化对象(使用new关键字并获取指针)或在堆栈上实例化(通过将其实例化为原始类型,即MyType myType;).通过告诉函数接受引用(&在声明中使用参数名之前的关键字),可以通过引用函数和方法来传递堆栈分配的项.这样做可以将堆栈分配的对象保留在内存中,只要分配它的方法仍在范围内; 一旦它超出范围,对象就会被回收,析构函数被称为ba-da-bing,ba-da-boom,Bob的你的叔叔,所有这些都是在没有指针的情况下完成的.
我使用这个技巧在我的C++时代创建了一些令人惊讶的高性能代码 - 牺牲了更大的堆栈和堆栈溢出的风险,当然,但仔细的分析设法使风险非常小.
我的观点是你可以使用结构和引用在C#中做同样的技巧.权衡?如果您不小心或者使用大型对象,除了存在堆栈溢出的风险之外,您不能继承,并且紧密耦合代码,使其不易测试且难以维护.此外,无论何时使用核心库调用,您仍然需要处理问题.
不过,在您的情况下,可能值得一看.
这是一个很难以一种有助于你的方式确定明确答案的问题之一..NET GC 非常善于根据应用程序的内存需求进行调整.在不需要担心内存管理的情况下编译应用程序是否足够好?我不知道.
肯定有一些常识性的事情可以确保你不会锤击GC.使用值类型绝对是实现此目的的一种方法,但您需要注意不要在编写不良的结构中引入其他问题.
但在大多数情况下,我会说GC会很好地管理所有这些东西.