如何提高创建具有多线程的批量对象的应用程序的性能?

时间:2015-05-19 13:40:00

标签: c# multithreading performance

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

我在一个简单的程序中测试了这个新SDK的性能,该程序创建了指定数量的线程,并在每个线程中循环调用API作为playload。使用1 thead,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会自然地创建一个对象,所以有办法解决吗?

我的一些猜测:

  1. .NET框架的内存分配有一个性能瓶网,所以当你平行创建对象时,你会受到影响。
  2. .NET框架的GC开始工作并大大降低了性能。

1 个答案:

答案 0 :(得分:0)

多线程编程的主要规则是,您不应该创建比CPU cores + 1更多的线程。这是因为您已经创建了许多线程,他们都试图同时完成工作,而您的CPU和操作系统会降低context switching的性能。这是非常耗时的操作 - 最好在同一个线程中完成两项工作,而不是两个线程完成一项工作。

有许多技术可以改善您的应用程序的性能,例如work stealing,但您应该自行调查,因为这是一个非常广泛的主题。