Web服务调用的多线程性能问题

时间:2009-02-03 13:40:54

标签: c# performance multithreading service

这是我的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;
    }
}

服务器端:

    [WebMethod]
    public double HelloWorld()
    {
        return new Random().NextDouble();
    }
提前谢谢, 乔治

9 个答案:

答案 0 :(得分:7)

虽然您正在创建多线程客户端,但请记住,.NET具有可配置的瓶颈,可同时调用2个单个主机。这是设计的。 请注意,这是在客户端,而不是服务器上。

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

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

this short article中有更多相关信息:

答案 1 :(得分:5)

我的经验通常是锁定是问题:我有一个大规模并行服务器,一次花费更多时间上下文切换而不是执行工作。

所以 - 检查你的内存并在perfmon中处理计数器,如果你看一下上下文切换及其高(每秒超过4000),那么你就麻烦了。

您也可以检查服务器上的内存统计信息 - 如果它花费所有时间交换,或者只是创建和释放字符串,它似乎也会停止。

最后,检查磁盘I / O,原因与上面相同。

解决方法是移除锁定,或保持锁定至少一段时间。通过消除对COM BSTR及其全局锁的依赖来解决我们的问题,你会发现C#有很多类似的同步瓶颈(旨在保证你的代码安全运行)。当我将一个简单的C#应用​​程序从单核移动到多核盒时,我已经看到性能下降。

如果你无法删除锁,那么最好的选择就是不要创建尽可能多的线程:)使用线程池代替让CPU在完成另一个工作之前完成一个工作。

答案 2 :(得分:3)

我不相信你实际上遇到了瓶颈。

你尝试过我的建议吗?

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

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

所以你的线程并没有像你想象的那样完全并行工作,你所看到的结果是可以预期的。

答案 3 :(得分:2)

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

return new Random().NextDouble();

Web服务调用涉及的开销高于您在其中进行的工作。如果您在服务中有一些实质性工作(数据库调用,查找,文件访问等),您可能会开始看到一些性能提升。 只是并行化任务不会自动使其更快。

-Jason

答案 4 :(得分:1)

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

但测试的重点是使用可变数量的线程进行测试。 因此,请将Sleep保留在WebMethod中。

现在尝试5,10,20个线程。

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

您意识到,在您的测试中,当您将线程数量增加一倍时,您正在将正在完成的工作量增加一倍。因此,如果你的线程没有真正并行执行,那么你当然会看到总时间的线性增长......

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

Sleep只会将线程的时间帧传递给另一个线程。

答案 8 :(得分:0)

IIS AppPool&#34;最大工作进程&#34;默认设置为1。出于某种原因,每个工作进程限制为一次处理10个服务调用。我的WCF异步服务器端功能执行睡眠(10 * 1000);只要。 当Maximum Worker Processes = 1时会发生这种情况 http://s4.postimg.org/4qc26cc65/image.png

替代地

http://i.imgur.com/C5FPbpQ.png?1

(关于SO的第一篇文章,我需要将所有图片合并为一张图片。)

客户端在此测试中正在进行48次异步WCF WS调用(使用16个进程)。理想情况下,这需要大约10秒才能完成(睡眠(10000)),但需要52秒。您可以在perfmon图片中看到5条水平线(上面的链接)(使用perfmon监视服务器中的Web Service Current Connections)。每条水平线持续10秒(睡眠(10000))。有5条水平线,因为服务器每次处理10个呼叫然后关闭10个连接(这发生5次以处理48个呼叫)。完成所有通话需要52秒。

设置最大工作进程数= 2 (在上面给出的相同图片中) 这次有3条水平线,因为服务器每次处理20个呼叫然后关闭那20个连接(这发生3次以处理48个呼叫)。花了33秒。

设置最大工作进程数= 3 (在上面给出的相同图片中) 这次有2条水平线,因为服务器每次处理30个呼叫。 (发生2次处理48次通话)花了24秒。

设置最大工作进程数= 8 (在上面给出的相同图片中) 这次有一条水平线,因为服务器每次处理80个呼叫。 (发生一次处理48个电话)花了14秒。

如果您不关心这种情况,您的并行(异步或线程)客户端调用将在服务器中排队10秒,然后所有线程调用(&gt; 10)都不会被处理由服务器并行。

PS:我使用的是Windows 8 x64和IIS 8.5。 10个并发请求限制适用于工作站Windows操作系统。服务器操作系统根据SO上的另一个帖子没有限制(由于rep&lt; 10,我无法提供链接)。