C# web服务调用的多线程性能问题

C# web服务调用的多线程性能问题,c#,performance,multithreading,service,C#,Performance,Multithreading,Service,这是我的web服务服务器端和客户端的示例程序。我遇到了一个strnage性能问题,即即使我增加了调用web服务的线程数量,性能也没有得到改善。同时,任务管理器性能面板的CPU/内存/网络消耗较低。我想知道什么是瓶颈以及如何改进它 (根据我的测试经验,线程数增加一倍将使总响应时间几乎增加一倍) 客户端: class Program { static Service1[] clients = null; static Thread[] threads = null; sta

这是我的web服务服务器端和客户端的示例程序。我遇到了一个strnage性能问题,即即使我增加了调用web服务的线程数量,性能也没有得到改善。同时,任务管理器性能面板的CPU/内存/网络消耗较低。我想知道什么是瓶颈以及如何改进它

(根据我的测试经验,线程数增加一倍将使总响应时间几乎增加一倍)

客户端:

class Program
{
    static Service1[] clients = null;
    static Thread[] threads = null;

    static void ThreadJob (object index)
    {
        // query 1000 times
        for (int i = 0; i < 100; i++)
        {
            clients[(int)index].HelloWorld();
        }
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Specify number of threads: ");
        int number = Int32.Parse(Console.ReadLine());

        clients = new Service1[number];
        threads = new Thread[number];

        for (int i = 0; i < number; i++)
        {
            clients [i] = new Service1();
            ParameterizedThreadStart starter = new ParameterizedThreadStart(ThreadJob);
            threads[i] = new Thread(starter);
        }

        DateTime begin = DateTime.Now;

        for (int i = 0; i < number; i++)
        {
            threads[i].Start(i);
        }

        for (int i = 0; i < number; i++)
        {
            threads[i].Join();
        }

        Console.WriteLine("Total elapsed time (s): " + (DateTime.Now - begin).TotalSeconds);

        return;
    }
}
提前感谢,,
George

根据我的经验,锁定通常是个问题:我曾经有一个大规模并行服务器,它在上下文切换上花费的时间比执行工作的时间要多

所以-在perfmon中检查内存和进程计数器,如果您查看上下文开关及其高值(每秒超过4000个),那么您就有麻烦了

你也可以在服务器上检查你的内存统计数据——如果它把所有的时间都花在交换上,或者只是创建和释放字符串上,那么它看起来也会暂停

最后,检查磁盘I/O,原因同上

解决方法是移除你的锁,或者将它们保持最短的时间。我们的问题是通过消除对COM BSTR及其全局锁的依赖而解决的,您会发现C#有很多类似的同步瓶颈(旨在确保代码安全运行)。当我将一个简单的C#应用程序从单核移动到多核机箱时,我看到了性能的下降


如果无法移除锁,最好的选择是不要创建尽可能多的线程:)使用线程池,让CPU先完成一个作业,然后再开始另一个作业。

好吧,在这种情况下,您并没有真正在所选的n.个线程之间平衡您的工作。。。您创建的每个线程将执行相同的作业。因此,如果创建n个线程,并且并行处理能力有限,那么性能自然会下降。另一个我注意到的是,所需的作业是一个相对快速的100次迭代操作,即使您计划通过多个线程划分该作业,也需要考虑在上下文切换中花费的时间,线程的创建/删除将是整个时间的一个重要因素。

尽管您正在创建一个多线程客户端,但请记住.NET有一个可配置的瓶颈,即对单个主机同时进行两次调用。这是故意的。 请注意,这是在客户机上,而不是服务器上

尝试在客户端中调整app.config文件:

<system.net>
<connectionManagement>
    <add address=“*” maxconnection=“20″ />
</connectionManagement></system.net>


正如布鲁诺所提到的,您的webmethod是一个非常快速的操作。作为一个实验,尝试确保HelloWorld方法需要更长的时间。加入一个线程。在返回随机双精度之前先休眠(1000)。这将使您的服务更有可能被迫并行处理请求。
然后使用不同数量的线程尝试您的客户端,看看性能有何不同。

我不认为您实际上遇到了瓶颈

你试过我的建议了吗

您的想法是添加更多线程以提高性能,因为您希望所有线程都能完美地并行运行。这就是为什么您假设线程数加倍不应使总测试时间加倍

您的服务需要几分之一秒的时间才能返回,并且您的线程在客户端上不会在完全相同的时间开始工作


因此,您的线程实际上并没有像您假设的那样完全并行工作,您看到的结果是可以预期的。

当然,添加睡眠不会提高性能

但是测试的重点是使用可变数量的线程进行测试。 所以,在你的方法中保持睡眠

现在尝试使用5、10、20个线程

如果代码没有其他问题,那么时间的增加就不应该像以前那样是线性的

您意识到,在测试中,当线程数量翻倍时,所做的工作量就翻倍了。所以,如果你的线程没有真正并行执行,那么你当然会看到总时间呈线性增加

我使用您的客户机代码运行了一个简单的测试(在服务上处于休眠状态)。 对于5个线程,我看到的总时间约为53秒。 10个线程,62秒。
因此,对于2倍于webservice的调用次数,只需多花17%的时间。。这就是你所期待的,不是吗

尝试使用一些消耗处理器的任务,而不是Thread.Sleep。实际上,组合方法是最好的


睡眠只会将线程的时间范围传递给另一个线程

您没有看到任何性能提升,因为没有任何性能提升。您的服务(下面)中的一行代码在大多数情况下都可能在没有上下文切换的情况下执行

return new Random().NextDouble();
web服务调用所涉及的开销高于您在其中所做的工作。如果您在服务内部有一些实质性的工作要做(数据库调用、查找、文件访问等),您可能会看到一些性能提高。 仅仅将任务并行化并不会自动使其更快

-Jason

IIS应用程序池“最大工作进程数”默认设置为1。由于某些原因,每个辅助进程一次只能处理10个服务调用。我的WCF异步服务器端函数不睡眠(10*1000);只有 这是最大工作进程数=1时发生的情况

或者

(因此,我需要将所有图片合并为一张图片。)

在此测试中,客户机正在进行48个异步WCF WS调用(使用16个进程)。理想情况下,这需要约10秒才能完成(睡眠(10000)),但需要52秒。您可以在perfmon图片(链接上方)中看到5条水平线(使用perfmon监视服务器中的Web服务当前连接)。每条水平线持续10秒(睡眠(10000)持续10秒)。有五个
return new Random().NextDouble();