代码之家  ›  专栏  ›  技术社区  ›  Trap

程序员是否应该真正关心在中创建对象的数量和/或频率。网?

  •  11
  • Trap  · 技术社区  · 16 年前

    我最近开始参与一个用Java编写的大型MMO项目(服务器端)。我的主要任务是优化内存消耗和CPU使用率。每秒发送数十万条消息,同时也创建了相同数量的对象。经过大量分析,我们发现VM垃圾收集器占用了大量CPU时间(由于持续的收集),并决定尽量减少对象创建,在适用的情况下使用池并重用我们能重用的一切。到目前为止,这已被证明是一个非常好的优化。

    那么,这也是真的吗。网?如果是,在多大程度上?

    // 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();
        ...
    }
    

    我有时也会在宁愿使用类的情况下编写结构,只是因为我知道会有数以万计的实例不断被创建和处理,这对我来说真的很奇怪。

    12 回复  |  直到 16 年前
        1
  •  9
  •   Randolpho    16 年前

    对于你的案例,你可能会考虑的一个优化——实际上,我一直在考虑写一篇文章——是结构和 ref

    由于你来自C++背景,你知道在C++中,你可以在堆上(使用new关键字并返回指针)或堆栈上(通过将其实例化为基元类型,即。 MyType myType; ).您可以通过告诉函数接受引用(使用 & 声明中参数名称前的关键字)。只要分配对象的方法仍在作用域内,这样做就会将堆栈分配的对象保留在内存中;一旦它超出作用域,对象就被回收,析构函数被调用,ba da bing,ba da boom,Bob的叔叔,所有这些都是在没有指针的情况下完成的。

    在我的C++时代,我使用这个技巧创建了一些性能惊人的代码——当然,这是以牺牲更大的堆栈和堆栈溢出的风险为代价的,但仔细的分析设法将这种风险降到了最低。

    不过,在你的案例中,这可能值得一看。

        2
  •  5
  •   Andrew Hare    16 年前

    这是一个很难以一种对你有帮助的方式确定明确答案的问题。这个。NET GC是 非常 擅长根据应用程序的内存需求进行调优。您的应用程序可以在不需要担心内存管理的情况下进行编码,这足够好吗?我不知道。

    当然,你可以做一些常识性的事情来确保你不会破坏GC。使用值类型绝对是实现这一点的一种方法,但你需要小心,不要用写得不好的结构引入其他问题。

    然而,在大多数情况下,我会说GC会很好地为你管理所有这些东西。

        3
  •  3
  •   Tad Donaghe    16 年前

    我见过太多的情况,人们“优化”了他们代码中的垃圾,而不太关心它的编写质量或工作效果。我认为第一个想法应该是让代码解决手头的业务问题。代码应该精心设计,易于维护,并且经过适当的测试。

        4
  •  3
  •   Drew Hoskins    16 年前

    随机建议:

    您可能在C#中使用的另一种技术是,对于性能不够好的关键部分,降级到本机C++。..然后使用 Dispose pattern 在C#或C++/CLI中,用于保存非托管资源的托管对象。

    最后,一定要找到一个好的内存分析器。

        5
  •  1
  •   User    16 年前

    我一直都有同样的想法。

    如果你意识到这一点并一直关注,我相信你可以编写不完美的代码。如果你已经开始了。NET/Java,并且之前没有低级编程经验,你很可能会编写非常滥用和无效的代码。

        6
  •  1
  •   BinaryMisfit    16 年前

    尽管有垃圾回收器,但坏代码仍然是坏代码。因此,我会说是的。Net开发人员,你仍然应该关心你创建了多少对象,更重要的是编写优化的代码。

        7
  •  1
  •   AutomatedTester    16 年前

    .NET内存管理非常好,如果需要,能够以编程方式调整GC是很好的。

        8
  •  1
  •   Jake Pearson    16 年前

        9
  •  1
  •   bryanbcook    16 年前

    我在代码审查中浪费了很多时间来讨论CLR的细节。最好的明确答案是在您的组织中培养一种绩效文化,并使用工具积极分析您的应用程序。瓶颈将出现,您可以根据需要解决。

        10
  •  1
  •   twon33    16 年前

        11
  •  1
  •   Cyberherbalist    16 年前

    我希望我是一个“软件传奇”,可以用自己的声音和呼吸来谈论这件事,但既然我不是,我就依靠SL来做这些事情。

    我建议安德鲁·亨特在上发表以下博客文章。NET GC会有所帮助:

    http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/

        12
  •  1
  •   supercat    12 年前

    即使在性能方面之外 修改传入可变对象的方法通常比基于旧对象返回新可变对象的方式更简洁。声明:

    munger.Munge(someThing, otherParams);
    someThing = munger.ComputeMungedVersion(someThing, otherParams);
    

    在某些情况下,行为可能相同,但前者只做一件事,后者只做两件事——相当于:

    someThing = someThing.Clone(); // Or duplicate it via some other means
    munger.Munge(someThing, otherParams);
    

    如果 someThing 是宇宙中任何地方对特定对象的唯一引用,那么用对克隆的引用替换它将是不可行的,因此修改传入的对象相当于返回一个新的对象。然而,如果, 某物 标识一个存在其他引用的对象,前一个语句将修改所有这些引用标识的对象,留下所有引用,而后者将导致 某物 变得“超然”。

    某物 以及它的使用方式、附着或分离可能是没有意义的问题。如果某个引用该对象的对象可以在其他引用存在的情况下对其进行修改,则附件将是相关的。如果对象永远不会被修改,或者外部没有引用,则附件没有意义 某物 某物 引用一个新对象就可以了。除非类型 某物 某物 ,因为。NET没有提供标准的方法来注释特定引用将标识一个对象,尽管该对象是可变类型的,但不允许任何人修改,也没有提供注释特定引用应该是 宇宙中任何地方识别特定物体的物体。