2013-01-02 111 views
0

我们正在使用WCF从服务器应用程序将数据传输到多个客户端WCF性能。实际上,对于大多数流量来说,客户端和服务器都运行在同一台机器上,所以我希望转移速度非常快。提高大型阵列

然而,传输大阵列(16位灰度图像)时,直到该数据被转移需要几秒钟。对于16 MB的图像,大约需要3-5秒!

最初,我们使用ushort阵列,因为它是用于存储16位灰度级图像数据的最适合的数据类型。但是,这非常缓慢:16 MB大约20-25秒。当我们使用Buffer.BlockCopy串行化前的数据复制到一个byte阵列,它被减小到3-5秒出于某种原因。然而,从一个应用程序传输16 MB到另一个在同一台计算机上运行的另一个应用程序需要3-5秒,这对我来说似乎还太长了!

因此,我的问题是:我们怎样才能改善这种情况下的表现?

我已经从Marc Gravell调查过protobuf-net,但我不确定这是否会对这种情况有所帮助......任何经验或其他建议?

这里是我们的数据类之一的源代码(包含图像数据):

[DataContract(IsReference = true)] 
public class ImageData 
{ 
    private ushort[] m_pixelData; 

    public ushort[] PixelData 
    { 
     get 
     { 
      return m_pixelData; 
     } 
     set 
     { 
      m_pixelData = value; 
      OnPropertyChanged("PixelData"); 
     } 
    } 

    [DataMember] 
    public override byte[] FileData 
    { 
     get 
     { 
      if (this.PixelData == null) 
      { 
       return null; 
      } 

      return ListHelper.ConvertToByteArray(this.PixelData); 
     } 
     set 
     { 
      if (value == null) 
      { 
       this.PixelData = null; 
       return; 
      } 

      this.PixelData = ListHelper.ConvertToUshortArray(value); 
     } 
    } 

} 

请注意,只有FileData属性标记为[DataMember],使PixelData属性不是序列!

这里是服务器的app.config相关部分:

<system.serviceModel> 
    <services> 
     <service name="Services.ImageDataService" behaviorConfiguration="ServicesBehavior"> 
      <host> 
       <baseAddresses> 
        <add baseAddress="net.tcp://localhost:8008/ImageDataService" /> 
       </baseAddresses> 
      </host> 
      <endpoint address="" binding="netTcpBinding" bindingConfiguration="NetTcpBindingLargeFileTransfer" contract="Services.IImageDataService" /> 
      <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange" /> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
      <behavior name="ServicesBehavior"> 
       <serviceMetadata httpGetEnabled="false" /> 
       <serviceDebug includeExceptionDetailInFaults="false" /> 
       <dataContractSerializer maxItemsInObjectGraph="2147483647"/> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <bindings> 
     <netTcpBinding> 
      <binding 
       name="NetTcpBindingLargeFileTransfer" 
       openTimeout="00:01:00" closeTimeout="00:01:00" receiveTimeout="infinite" sendTimeout="infinite" 
       transactionFlow="false" transactionProtocol="OleTransactions" 
       transferMode="Buffered" hostNameComparisonMode="StrongWildcard" listenBacklog="10" 
       maxBufferPoolSize="2097152" maxBufferSize="1073741824" maxConnections="10" maxReceivedMessageSize="1073741824"> 
       <readerQuotas 
        maxDepth="2147483647" maxStringContentLength="2147483647" 
        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
       <reliableSession ordered="true" inactivityTimeout="infinite" enabled="false" /> 
       <security mode="None"> 
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> 
        <message clientCredentialType="Windows" /> 
       </security> 
      </binding> 
     </netTcpBinding> 
    </bindings> 
</system.serviceModel> 

和客户端的app.config

<system.serviceModel> 
    <bindings> 
     <netTcpBinding> 
      <binding 
       name="NetTcpBindingLargeFileTransfer" 
       openTimeout="00:01:00" closeTimeout="00:01:00" receiveTimeout="infinite" sendTimeout="00:10:00" 
       transactionFlow="false" transactionProtocol="OleTransactions" 
       transferMode="Buffered" hostNameComparisonMode="StrongWildcard" listenBacklog="10" 
       maxBufferPoolSize="2097152" maxBufferSize="1073741824" maxConnections="10" maxReceivedMessageSize="1073741824"> 
       <readerQuotas 
        maxDepth="2147483647" maxStringContentLength="2147483647" 
        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
       <reliableSession ordered="true" inactivityTimeout="infinite" enabled="false" /> 
       <security mode="None"> 
        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> 
        <message clientCredentialType="Windows" /> 
       </security> 
      </binding> 
     </netTcpBinding> 
    </bindings> 
    <client> 
     <endpoint 
      address="net.tcp://localhost:8008/ImageDataService" 
      binding="netTcpBinding" 
      bindingConfiguration="NetTcpBindingLargeFileTransfer" 
      contract="Services.IImageDataService" 
      name="Services.IImageDataService" 
      behaviorConfiguration="ServicesBehavior" /> 
    </client> 
    <behaviors> 
     <endpointBehaviors> 
      <behavior name="ServicesBehavior"> 
       <dataContractSerializer maxItemsInObjectGraph="2147483647"></dataContractSerializer> 
      </behavior> 
     </endpointBehaviors> 
    </behaviors> 
</system.serviceModel> 

回答

2

在同一台机器上尝试命名管道。

Choosing a Transport

+1

谢谢!这将转换时间缩短了一半!我没有想到这个,因为也有远程客户端,即在其他机器上。但是,图像数据通常不通过网络传输。因此使用'NetNamedPipeBinding'添加另一个端点是一种可行的方法。 – gehho

1

尝试使用命名管道传输流。有关详细信息,请参阅这篇文章Large Data and Streaming

这可能是其发送到服务器/客户端之前缓冲数据时出现问题。流式传输将以块形式发送数据。

+0

我前段时间已经看过流媒体。但是,它甚至让它变得更慢了。也许数据量不足以通过流式传输获得性能提升。从我在互联网上阅读的内容中,我了解到流式传输更适用于大型数据项目,例如500 MB左右。 – gehho

+0

你是否也尝试使用命名管道? –

+0

如上所述(其他答案),命名管道将传输时间缩短了一半。 – gehho