1

サーバーアプリケーションから複数のクライアントにデータを転送するためにWCFを使用しています。実際、ほとんどのトラフィックでは、クライアントとサーバーが同じマシンで実行されているため、転送は非常に高速であると予想されます。

ただし、大きな配列 (16 ビット グレースケール イメージ) を転送する場合、データが転送されるまでに数秒かかります。16 MB のイメージの場合、約 3 ~ 5 秒かかります。

最初は、ushort16 ビットのグレースケール イメージ データを格納するのに最も適したデータ型であるため、配列を使用していました。ただし、これは非常に遅く、16 MB で約 20 ~ 25 秒かかりました。byteを使用してシリアル化する前にデータを配列にコピーするとBuffer.BlockCopy、何らかの理由で 3 ~ 5 秒に短縮されます。ただし、16 MB を同じマシン上で実行されている別のアプリケーションに転送するのに 3 ~ 5 秒かかるのは、やはり私には長すぎるように思えます。

したがって、私の質問は次のとおりです。このようなシナリオのパフォーマンスをどのように改善できますか?

私はすでに Marc Gravell から protobuf-net を調査しましたが、この場合に役立つかどうかはわかりません...経験やその他の提案はありますか?

以下は、データ クラス (画像データを含む) の 1 つのソース コードです。

[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>
4

2 に答える 2

2

同じマシンで名前付きパイプを試してください。

交通機関の選択

于 2013-01-02T14:02:30.277 に答える
1

名前付きパイプ トランスポートでストリーミングしてみてください。詳細については、この投稿を参照してください。大規模なデータとストリーミング

サーバー/クライアントに送信する前にデータをバッファリングする際に問題が発生する可能性があります。ストリーミングは、データをチャンクで送信します。

于 2013-01-02T16:02:57.113 に答える