可以做些什么来加速同步WCF调用?

时间:2010-03-09 07:55:14

标签: wcf silverlight performance

我在Silverlight应用程序中对同步WCF调用的性能测量表明,我可以在localhost连接上进行 7次调用非常慢。这可以加速,还是这是正常的?

这是我的测试代码:

const UInt32 nrCalls = 100;
ICalculator calculator = new CalculatorClient(); // took over from the MSDN calculator example
for (double i = 0; i < nrCalls; ++i)
{
    var call = calculator.BeginSubtract(i + 1, 1, null, null);
    call.AsyncWaitHandle.WaitOne();
    double result = calculator.EndSubtract(call);
}

说明

  • CPU负载几乎为0%。显然,WCF模块正在等待。
  • 我在Firefox 3.6和Internet Explorer 7上都测试过这个。
  • 我正在使用Silverlight v3.0
  • 为了比较:我曾经用C ++编写了一个IPC库,类似的测试产生了一些 4000个调用/ s 。那是没有HTTP数据包包装器,但我不希望这会减慢很多东西。这只是7个电话/秒非常慢。

更新:我已将客户端从Silverlight移植到.NET,这解决了性能问题。在该测试中,同步呼叫在 140个呼叫/ s (而不是7个呼叫/秒)进行,异步呼叫以200个呼叫/秒(而不是16个呼叫/秒)进行。显然, Silverlight平台固有的缓慢。我必须学会忍受它。

2 个答案:

答案 0 :(得分:4)

不是很多。你运行100个http调用的问题,这需要时间。你不是每次都要通过生成一个新客户来吹嘘....所以,对不起。

一般来说,这是一个不好的例子(或者是一个表现不好的好习惯)。服务应始终粗粒度以避免呼叫开销。一般来说,服务应该具有一定的“权重”。

计算器可以接受一系列操作,因此所有100次计算都可以一次发送,例如。

在设计自己的界面时请记住这一点。

答案 1 :(得分:1)

使用异步调用并并行运行它们。

互联网速度如此之快。实际上,您发送请求,等待永恒(1)消息到达服务器,(2)服务器响应,(3)回复的响应。 (1)和(3)需要时间;也许,有些东西比如“服务器里程”和“光速”。然后你发送下一个请求并再次进行相同的等待游戏。然后再次。在循环中。

因此异步调用和并行请求= win。

(提示:如果使用F#,异步可以非常简单,如下面的示例所示。)

open System
open System.Diagnostics 
open System.ServiceModel 

let binding = new BasicHttpBinding()
let address = "http://YOURSERVERMACHINENAME:11111/Blah"

#if SERVER
[<ServiceContract>]
type IMyContract =
    [<OperationContract>]
    abstract member Subtract : x:int * y:int -> int

type MyService() =
    interface IMyContract with
        member this.Subtract(x,y) = x-y

let host = new ServiceHost(typeof<MyService>, new Uri(address))
host.AddServiceEndpoint(typeof<IMyContract>, binding, address) |> ignore
let smb = new Description.ServiceMetadataBehavior()
smb.HttpGetEnabled <- true
host.Description.Behaviors.Add(smb)
host.Open()
Console.WriteLine("service is open")

#else

[<ServiceContract(Name="IMyContract")>]
type IMyClientContract =
    [<OperationContract>]
    abstract member Subtract : x:int * y:int -> int
    [<OperationContract(AsyncPattern=true)>]
    abstract member BeginSubtract : x:int * y:int * c:AsyncCallback * o:obj -> IAsyncResult
    abstract member EndSubtract : r:IAsyncResult -> int

let client = ChannelFactory<IMyClientContract>.CreateChannel(binding, new EndpointAddress(address))
let MAX = 30

let syncSw = Stopwatch.StartNew()
[1..MAX] |> Seq.iter (fun i -> 
    let r = client.Subtract(i,1)
    Console.WriteLine(r))
Console.WriteLine("sync took {0}ms", syncSw.ElapsedMilliseconds)

let AsyncSubtract(x,y) = Async.FromBeginEnd(x, y, client.BeginSubtract, client.EndSubtract)

let asyncSw = Stopwatch.StartNew()
[1..MAX] |> Seq.map (fun i -> async {
    let! r = AsyncSubtract(i,1)
    Console.WriteLine(r)}) 
    |> Async.Parallel |> Async.RunSynchronously |> ignore
Console.WriteLine("async took {0}ms", asyncSw.ElapsedMilliseconds)
#endif

Console.WriteLine("press a key to quit")
Console.ReadKey()