使用“using”语句在单元测试中的性能影响

3
我有一个本地托管的WCF服务,提供一个基本方法,返回你传递给它的字符串值。
我还有一个单元测试,在其中尝试调用该服务10000次,并监测调用完成所需的时间。
在我的测试中,using语句的位置至关重要,如果放置不当,会产生很大的差异,然而我不理解为什么会出现这种情况。
示例1:(35秒)
    [TestMethod]
    public void TestGetDataOutsideUsing()
    {
        const int count = 10000;
        var operations = new List<int>();
        for (var i = 0; i < count; i++)
            operations.Add(i);
        using (var proxy = new BasicHttpServiceClient())
        {
            var timer = Stopwatch.StartNew();
            System.Threading.Tasks.Parallel.ForEach(operations, x => { proxy.GetData(x.ToString(CultureInfo.InvariantCulture)); });
            timer.Stop();
            Console.WriteLine("{0:###0.0000000} ms", timer.ElapsedMilliseconds);
            Console.WriteLine("{0:###0.0000000} per millisecond", (count / (decimal)timer.ElapsedMilliseconds));
            Console.WriteLine("{0:###0.0000000} per second", (count / ((decimal)timer.ElapsedMilliseconds / 1000)));
            Console.WriteLine("{0:###0.0000000} per minute", (count / ((decimal)timer.ElapsedMilliseconds / 1000 / 60)));
        }
    }

例子2: (6.2秒)

    [TestMethod]
    public void TestGetDataInsideUsing()
    {
        const int count = 10000;
        var operations = new List<int>();
        for (var i = 0; i < count; i++)
            operations.Add(i);
        var timer = Stopwatch.StartNew();
        System.Threading.Tasks.Parallel.ForEach(operations, x =>
            {
                using (var proxy = new BasicHttpServiceClient())
                {
                    proxy.GetData(x.ToString(CultureInfo.InvariantCulture));
                }
            });
        timer.Stop();
        Console.WriteLine("{0:###0.0000000} ms", timer.ElapsedMilliseconds);
        Console.WriteLine("{0:###0.0000000} per millisecond", (count / (decimal)timer.ElapsedMilliseconds));
        Console.WriteLine("{0:###0.0000000} per second", (count / ((decimal)timer.ElapsedMilliseconds / 1000)));
        Console.WriteLine("{0:###0.0000000} per minute", (count / ((decimal)timer.ElapsedMilliseconds / 1000 / 60)));
    }

第一个和第二个示例之间唯一的区别是using语句的位置。我本以为在ForEach内部使用using语句会更耗时,但实际上证明了相反的情况。

为什么会这样,并且上述示例中哪一个才是正确测试的方式?也许我正在错误地进行此测试?

我想做的只是对我的服务进行10000个并发调用并查看所需时间。


2
在代码中使用 using 语句来实例化客户端代理是一种不好的做法,可以在 StackOverflow 上搜索“如何关闭客户端 WCF 代理”。 - sll
5
这是否与第一个示例中每个线程共享相同的代理有关,因此它们不能并行执行? - levelnis
@sll 谢谢,我之前不知道这个。会查阅相关信息并确保实例化和卸载的正确处理。 - Matei
2个回答

4
在第一个示例中,有一个单独的Proxy对象;在第二个示例中,有多个Proxy对象。
我认为这与using语句没有直接关联,而是与其使用方式有关。在第一个示例中,Proxy对象成为并行操作的瓶颈。

2

这是两件非常不同的事情:

  • 在第一个例子中,您在单个代理对象上运行多个线程,这有效地序列化了处理1并破坏了并行性。
  • 在第二个例子中,每个线程都有自己的代理对象,这使它可以与其他线程独立运行(并发运行)。

工作量多少相等2,但第二个例子更快完成,因为更多的工作可以并行完成。


1 我假设在其中某个地方有一个锁定,否则您将面临竞态条件。

2 不考虑创建所有这些代理的成本。


谢谢您的见解,我现在理解得更清楚了。示例1对于我需要测试所做的事情是不相关的。 - Matei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接