5

(这是一个一般性的假设性问题,我抱怨 .NET 是一头猪,并乞求理由。这并不是关于我的特定应用程序的问题。)

目前我正在用 C# 重写一些旧的 C++ 代码。我们正在移植所有遗留应用程序。我有占用 MAX 3% CPU 的 C++ 应用程序。大多数情况下,他们没有使用。然后我获取代码,复制和粘贴,然后重新格式化为 C# 语法和 .NET 库,然后 BAM!50% 中央处理器。这是什么原因?起初我以为是 JIT,但即使在每个代码路径都经过练习之后,整个事情都是 JIT 编辑的,同样的问题。

我还注意到巨大的内存增加。运行满负载需要 9 MB 的应用程序现在以 10 MB 启动并以 50 MB 运行。我意识到硬件很便宜,但我想了解是什么原因造成的。这是引起恐慌的原因,还是 .NET 就是这么一头猪?

更新 1 对 Skeet 的回答

我熟悉 C#。我将事情更改为 Linq,等等。我通常采用代码并减少行数,等等。您能否提供更多示例说明我在 .NET 中做错了什么?

更新 2

这是一个普遍的问题,但有问题的特定应用程序如下。

它有一个线程,使用 ODBC 驱动程序从 paradox db 获取数据。然后它使用 Linq 将其转换为 SQL 数据库并发布。我已经通过 ANTS 分析器运行它,似乎数据集填充花费的时间最多。紧随其后的是 Linq 发帖。我知道我的一些领域是反射使用,但我不知道如何做我需要做的事情。我计划将我的字符串更改为字符串生成器。这两者有什么区别吗?

(int)datarow["Index"]

ConvertTo.Int32(datarow["Index"])

我将所有字符串连接更改为格式化字符串。这并没有减少开销。有人知道数据阅读器与数据适配器和数据集之间的区别吗?

4

5 回答 5

17

您对 C# 和 .NET 的熟悉程度如何?如果您只是移植保留 C++ 习语的遗留代码,我一点也不惊讶它是一个猪。将应用程序从一个平台逐字移植到另一个平台几乎从来都不是一个好主意。(当然,您并没有说您肯定已经这样做了。)另外,如果您是 C++ 开发专家,但 .NET 开发新手,您应该期望您的代码在平台上像新手一样执行

如果不了解更多有关该应用程序的信息,我们无法真正说出性能的原因 - 尽管听到字符串连接是罪魁祸首我不会感到惊讶。盒子上有多少个处理器?如果它是 2,那么该应用程序基本上占用了它可以为单个线程提供的所有内容......

.NET 在内存方面通常会比 C++ 应用程序更重,但在大多数任务的速度方面至少应该是可比的。使用 50MB 而不是 9MB 听起来比我预期的要多,但我不会立即担心。

应使用良好的分析器来研究内存和 CPU 性能。我可以推荐JetBrains dotTrace Profiler,但还有很多其他的。

于 2009-09-15T19:31:03.090 回答
6

(int)datarow["Index"]AFAIK和之间有一点区别ConvertTo.Int32(datarow["Index"])。但是,如果您使用流模式数据读取器,则会有很大的不同:

int orderIndex = <order of Index column in projection list>;
using (OdbcDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
  int Index = rdr.GetInt32(orderIndex);
}

命令行为是处理 SQL 结果的SeqentialAccess最快方式,因为它确实消除了随机访问所需的额外缓存。

第二个通知是您似乎正在使用数据集。数据集易于使用,但与任何人所说的“快速”相去甚远。使用数据集,您基本上是在运行一个内存存储引擎(我认为是基于Rushmore的)。如果您想从每个位的 RAM 中压缩每个 CPU 周期和所有 1,那么您将不得不使用更精简的组件(例如,结构的原始数组而不是数据集和数据表)。

当您将苹果与苹果进行比较时,CLR 可以与本机代码保持一致。IL 代码可以在部署时使用NGEN进行本地化。可以避免边界检查等典型的 CLR 开销。GC 抢占“暂停”仅在您不小心分配时才会发生(仅仅因为您有 GC 并不意味着您应该分配左右)。CLR 在内存布局方面实际上有一些优势,因为它可以重新排列内存中的对象以适应访问模式并改善 TLB 和 L2 局部性。

顺便说一句,如果您认为“C++ 可以围绕 C# 循环运行”的辩论是新事物,我记得有一段时间 C 可以围绕 C++ 循环运行(他们说“虚拟调用非常慢”),我听说有一个时间汇编绕着 C 转圈。

于 2009-09-15T20:24:25.027 回答
1

您应该会看到 CPU 使用率有所增加。3% 到 50% 听起来太多了,这是什么代码?

内存占用只是不可避免的成本。.NET 应用程序在 30-50 MB 之间的任何内容都是正常的。通常,您的 .NET 应用程序的实际内存使用量非常小,但是您无法避免相当大的运行时开销(这是一次性成本,但它就在那里),如果您引用大量程序集,它会非常明显.

于 2009-09-15T19:32:27.160 回答
0

我能想到几个猜想:

1) 内存 - C++ 没有托管内存。因此,它会在(如果编程良好)最佳时间逐步释放内存。

使用托管内存,程序基本上会“泄漏”内存,直到它选择进行垃圾回收。时间可能取决于分配给进程的内存量。可能有一种方法可以更改默认行为,但较小的内存大小意味着垃圾收集会更快更频繁地进行,这会影响处理时间。如果分配了足够的 memo9ry,则 gc 可能不需要被 inv9ked。

2)程序是否在同一时间运行,还是更少?如果它使用 5 倍的处理器能力但在 1/5 的时间内完成,那么使用的 CPU 基本上是等效的。

3) 是的,.NET 可能是一头猪

于 2009-09-15T19:37:12.093 回答
0

我会说内存使用率可能是一致的,但 CPU 使用率不是。

听起来你有一个不屈服的线程。

于 2009-09-15T19:31:22.480 回答