如何提高多线程创建大量对象的应用程序的性能



我正在为NoSQL数据库编写一个c# SDK,为了处理请求(例如序列化或反序列化,签名),我必须创建很多(小)对象。

我在一个简单的程序中测试了这个新SDK的性能,该程序创建了指定数量的线程,并在每个线程中循环调用api作为playload。对于1个线程,QPS达到6K+,但随着线程数的增加,总体QPS下降而不是增加。

为了找出原因,我简化了我的测试程序,并将有效负载减少到一个非常简单的代码中,而不是实际调用我的SDK接口:

for (int i = 0; i < 100000; i ++) {
    double a = Math.Pow(3.14, 0.5);
}

性能结果很好:

1线程132 QPS
2个线程261 QPS
4个线程1028 QPS
8线程1826 QPS

但是当我将有效载荷更改为:

for (int i = 0; i < 100000; i ++) {
    var c = new string('X', 50);
}

性能如下:

1线程300 QPS
2个线程497 QPS
4个线程596 QPS
8线程518 QPS

如果我在负载中创建一些其他对象,结果将是相同的(不是线性的)。

(以上两种情况均未达到CPU和内存限制)

为什么?我的SDK自然会创建一个对象,有办法解决吗?

我的一些猜想:

    . net框架的内存分配有性能瓶颈,所以当你并行创建对象时,你会受到影响。
  1. . net框架的GC开始工作并显著降低了性能。

多线程编程的主要规则是您不应该创建多于CPU cores + 1的线程。这是因为您创建了许多线程,它们都试图同时完成它们的工作,并且您的CPU和操作系统降低了context switching的性能。这是一个非常耗时的操作——在同一个线程中做两件工作比在两个线程中做一件工作要好。

有很多技术可以提高应用程序的性能,例如,窃取工作,但你应该自己研究,因为这是一个非常广泛的话题。

最新更新