带有C#和C+的GC+;同一溶液

带有C#和C+的GC+;同一溶液,c#,c++,multithreading,garbage-collection,C#,C++,Multithreading,Garbage Collection,我有一个由许多C#项目组成的解决方案。它是用C#编写的,以使它能够快速运行。垃圾收集开始成为一个问题,我们希望避免大约100毫秒的延迟 一个想法是用C++来重写它,按项目进行。但是如果将C++与非托管C++相结合,C++项目中的线程也会被垃圾回收冻结吗? 更新 谢谢你的回复。事实上,这是一个100毫秒可能意义重大的应用程序。在C#中构建它可能是一个糟糕的决定,但当时它必须快速启动并运行 现在,我们正在使用Windows每5毫秒触发一次事件。我们确实看到大约100毫秒以上的间隔,我们通过检查GC计

我有一个由许多C#项目组成的解决方案。它是用C#编写的,以使它能够快速运行。垃圾收集开始成为一个问题,我们希望避免大约100毫秒的延迟

一个想法是用C++来重写它,按项目进行。但是如果将C++与非托管C++相结合,C++项目中的线程也会被垃圾回收冻结吗? 更新 谢谢你的回复。事实上,这是一个100毫秒可能意义重大的应用程序。在C#中构建它可能是一个糟糕的决定,但当时它必须快速启动并运行


现在,我们正在使用Windows每5毫秒触发一次事件。我们确实看到大约100毫秒以上的间隔,我们通过检查GC计数器确认,这些间隔总是在收集过程中发生。优化正在进行中;内置发布模式。

首先,您是否尝试过分析内容,看看是否可以优化内存使用?一个很好的起点是使用(适用于3.5以下的所有CLR)


重写C++中的所有东西只是为了一个小的性能命中,这是一个非常巨大的变化,就像是用截断你的手来修复一个剪纸。

< P>你确信100Ms的延迟是由于GC吗?我会非常确信GC实际上是你的问题,然后你花很多时间、精力和金钱重写C++中的东西。将托管代码与非托管代码相结合也会带来自身的问题,因为您必须处理这两个上下文之间的封送。这将增加其自身的性能损耗,最终你的净收益很可能为零

我会对你的C#应用程序进行分析,并缩小你100毫秒延迟的确切范围。此工具可能有帮助:

GC上的一个单词

关于.NET GC的另一个词(或者实际上是任何GC),这个词几乎不常被提及,但它是成功使用GC编写代码的一个关键因素:

拥有垃圾收集器并不意味着你不必考虑内存管理

<>编写与GC匹配得好的最佳代码需要比编写与非托管堆很好地播放的C++代码更少的努力和麻烦……但是,您仍然需要理解GC和与它友好地运行的编写代码。您不能完全忽略所有与内存管理相关的事情。你必须少担心它,但你仍然必须思考它。编写与GC配合良好的代码是实现不会产生内存管理问题的高性能代码的一个至关重要的因素

下面的文章也应该是有帮助的,因为它概述了.NET GC的基本行为(通过.NET 3.5有效…这篇文章很可能不再完全适用于.NET 4.0,因为它的GC有一些关键更改…首先,它不再需要在收集发生时阻塞.NET线程):


如果100毫秒是一个问题,我认为您的代码是任务关键型的。混合使用托管代码和非托管代码将导致托管appdomain和非托管空间之间调用的互操作开销


GC经过了很好的优化,所以在进行优化之前,请尝试分析代码并对其进行重构。如果您关心GC,请尝试设置线程优先级,尽可能减少对象创建和缓存数据。在项目中,属性也会打开优化代码设置。

CLR GC不会在收集期间挂起运行非托管代码的线程。如果本机代码调用托管代码,或返回托管代码,则它可能会受到集合的影响(与任何其他托管代码一样)

一个想法是用C++来重写它,按项目进行。但是如果将C++与非托管C++相结合,C++项目中的线程也会被垃圾回收冻结吗? <如果C++代码在不同线程上运行,则不能。C++堆和托管堆是不同的东西。p> 另一方面,如果C++代码正在进行大量的新/删除,那么当堆被碎片化时,您仍然会看到C++代码中的分配档位。这些停顿可能比你在C代码中看到的要糟糕得多,因为没有GC。当堆需要清理时,它只发生在对new或delete的调用中


如果您确实有严格的性能要求,那么您需要计划在时间关键型代码中不从常规堆进行任何内存分配。在实践中,这意味着这将更像C代码而不是C++代码,或者使用特殊的内存池和放置新。

< P>我在一家贸易公司工作。NET开发人员,像你一样,我们关心100毫秒的延迟。当需要可靠的最小延迟时,垃圾收集确实会成为一个重要问题

P>以上,我认为迁移到C++是明智之举,主要是因为它会耗费时间。垃圾收集发生在堆上分配了一定数量的内存之后。通过最小化代码创建的堆分配量,可以大大缓解这个问题

我建议您尝试找出应用程序中负责大量分配的方法。构建对象的任何地方都将成为修改的候选对象。对抗垃圾收集的一种经典方法是利用资源池:不是每次调用一个方法时都创建一个新对象,而是维护一个已构建的对象池,在每次方法调用时从池中借用,并在方法完成后将对象返回到池中

另一个不用动脑筋的方法是在代码框中查找任何
数组列表
哈希表
,或类似的非泛型集合