C# 性能因内存而异

标签 c# .net performance memory memory-management

希望这是一篇有效的帖子,它结合了 C# 问题和硬件。

我正在对我们的服务器进行基准测试,因为我们发现了 quant 库(用 C# 编写)的性能问题。我用一些简单的 C# 代码模拟了相同的性能问题——执行非常重的内存使用。

下面的代码是从线程池中生成的一个函数,最多有 32 个线程(因为我们的服务器有 4 个 CPU,每个有 8 个内核)。

这一切都在 .Net 3.5 上

问题是我们得到了截然不同的性能。我运行以下函数 1000 次。代码运行的平均时间可能是 3.5 秒,但最快的只有 1.2 秒,最慢的只有 7 秒——对于完全相同的功能!

我已经根据时间绘制了内存使用情况,似乎与 GC 启动没有任何关联。

我确实注意到的一件事是,在单线程中运行时,时间是相同的,并且没有明显的偏差。我还测试了受 CPU 限制的算法,并且时间也相同。这让我们怀疑内存总线是否无法应对。

我想知道这可能是另一个 .net 或 C# 问题,还是与我们的硬件有关?如果我使用 C++ 或 Java,这会是同样的体验吗?我们使用的是 4x Intel x7550 和 32GB 内存。一般有什么办法可以解决这个问题吗?

Stopwatch watch = new Stopwatch();
watch.Start();
List<byte> list1 = new List<byte>();
List<byte> list2 = new List<byte>();
List<byte> list3 = new List<byte>();


int Size1 = 10000000;
int Size2 = 2 * Size1;
int Size3 = Size1;

for (int i = 0; i < Size1; i++)
{
    list1.Add(57);
}

for (int i = 0; i < Size2; i = i + 2)
{
    list2.Add(56);
}

for (int i = 0; i < Size3; i++)
{
    byte temp = list1.ElementAt(i);
    byte temp2 = list2.ElementAt(i);
    list3.Add(temp);
    list2[i] = temp;
    list1[i] = temp2;
}
watch.Stop();

(代码只是为了强调内存)

我会包含线程池代码,但我们使用了非标准线程池库。

编辑:我已将“size1”减少到 100000,这基本上不会使用太多内存,但我仍然会得到很多抖动。这表明不是传输的内存量,而是内存抢占的频率?

最佳答案

没有足够的继续,但这里有一些领域可以开始寻找:

  • 可变性是内部 GC 状态的结果。 GC 动态管理各种池的大小。如果您从不同的池大小开始,您将在运行期间获得不同的 GC 行为。
  • 线程调度中的摩尔纹。根据线程顺序的随机变化,您可能会有或多或少有利的争用模式。如果存在任何周期性,则可能会导致类似于相长干涉的放大效应。
  • 虚假分享。如果您有两个线程都命中足够接近的内存地址以位于处理器缓存中,您将看到性能显着下降,因为处理器必须花费大量时间重新同步它们的缓存。根据您组织数据和分配线程来处理数据的方式,您可能会在开始时根据变化获得虚假共享模式。
  • 系统中的另一个进程正在占用处理器时间。您可能希望使用进程用户模式时间而不是挂壁时间的度量。 (Process 类中有一个访问器)。
  • 计算机的运行速度已接近其完整的物理内存限制。以或多或少的随机模式交换到磁盘。

关于C# 性能因内存而异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9997316/

相关文章:

c# - 我如何断言 Observable 不会推送任何项目?

python - 大于阈值的元素的 numpy.argmin

c# - 如何验证复合控件

java - 所有重复的单词

c# - 有没有办法让字符串达到年份值?

performance - 存储 RISK 或 Total War 等游戏中关卡的数据

java - 在这种情况下 String.format 会导致性能问题吗?

c# - 如何使用ffmpeg从视频文件中提取图像流

C# 使用 "Forbidden"错误将 SSL 证书获取到 X509Certificate

c# - IIS7.5 WCF 服务 - HTTP 错误 401.3(即使在添加 IIS_IUSRS 之后)