2012-10-11 6 views
11

Ich habe seit ein paar Tagen mit einem Problem mit unseren WPF-Anwendungen gekämpft und ich frage mich, ob jemand schon einmal darauf gestoßen ist und helfen kann? Das Problem scheint auf den Client herunterzufallen, der "on-the-fly" einen Serializer generiert, um die Typen in diesem Webmethodenaufruf zu verarbeiten. Wenn diese Methode zum ersten Mal aufgerufen wird (der Web-Dienst selbst wurde bereits ausgeführt), kann es z. 8 Sekunden können nachfolgende Anrufe z.B. 20ms. Die CPU im Client-WPF-Prozess ist während dieser Verzögerung v.Verwendung von WCF aus WPF sehr langsam bei der ersten Verwendung

Wenn Sie den XmlSerializer verwenden, können Sie diese Serializer-Assemblys mit svcutil vorgenerieren. Wenn (wie wir) den normalen WCF DataContractSerializer verwenden, scheint diese Option nicht vorhanden zu sein.

Was ich möchte, ist in der Lage, diese Baugruppe für alle Typen in allen meinen Datenverträgen (viel) vorzugenerieren oder alternativ diesen Prozess durch einen benutzerdefinierten zu ersetzen, den ich kodieren kann und die Daten weitergibt binär (wir besitzen beide Enden dieses Webservice/Clients und sie sind beide .NET 4). Ich habe bereits BinaryFormtter und GZip-Komprimierung verwendet, und während dies die Übertragung von Daten beschleunigt, wird es immer wieder in XML wiederhergestellt, um durch das Framework deserialisiert zu werden, daher bleibt dieses Problem bestehen.

Irgendwelche Ideen?

Antwort

8

Sie können eine binäre Bibliothek wie protobuf-net verwenden, die ziemlich schnell ist, selbst wenn es anfängliche Startkosten gibt, weil Code für jeden Typ generiert werden muss, ist es immer noch way better than DataContractSerializer or BinaryFormatter. Sie sollten ein paar Sekunden gewinnen und eine insgesamt flüssigere Erfahrung haben. Es kann easily integrated with WCF sein. Beachten Sie, dass WCF Ihre verschiedenen Verträge weiterhin prüft, um die korrekte WSDL und verschiedene Metadaten zu generieren.

Es gibt andere Dinge, die den WCF-Start verlangsamen können, z. B. das Bestimmen des Standard-Web-Proxys. Stellen Sie sicher, dass useDefaultWebProxy in Ihrer Bindungskonfiguration false ist, wenn Sie keine Verwendung dafür haben.

Noch, Sie werden feststellen, dass WCF-Start ist in der Regel langsam, egal was Sie tun, um es zu optimieren. Persönlich, müde von der Bekämpfung der Langsamkeit in einem ähnlichen Szenario (ich kontrollierte beide Enden, und der Client war eine WPF-Anwendung), ich einfach WCF aufgegeben und ging für ServiceStack + Protobuf-net. Der erste Anruf ging von 2-3 Sekunden auf ~ 100 ms, und alle folgenden HTTP-Anrufe sind wirklich sofort. Die allgemeine Benutzerfreundlichkeit hat sich stark verbessert. Beachten Sie, dass ich in keiner Weise mit ServiceStack verbunden bin, dies ist nur meine Erfahrung.

+0

Danke Julien, ich habe useDefaultWebProxy false bereits. Ich habe versucht, protobuf-net zu verwenden, aber ich habe Schwierigkeiten zu verstehen, ob ich alle meine Datentypen mit einem neuen Attribut neu dekorieren muss - ich hoffe nicht. Es sagt auf der Website, dass v2 "ohne Attribute verwendet werden kann, wenn Sie möchten", aber alle Beispiele verwenden Attribute. Wird dies die Startgeschwindigkeit des ersten Anrufs sogar in IIS verbessern (was wirklich vorgeschrieben ist), d. H. Ist der Protobuf-Net-Serializer zum Zeitpunkt der Erstellung vorgeneriert? –

+0

@SimonEvans, solange Sie die 'Order'-Eigenschaft auf jedem' DataMember 'gesetzt haben, sollte es Ihnen gut gehen. Habe es allerdings nicht selbst benutzt (ich ging von Anfang an mit protobuf). –

+0

Julien, meinst du ich müsste [ProtoMember (n)] zu jedem öffentlichen Eigentum hinzufügen? Danke für Ihre Hilfe –

0

Sie können die Kaltstartzeit verbessern, indem Sie Ihren WCF-Dienst vorab laden ... d. warten Sie nicht auf die erste Anfrage, um es zu laden ... laden Sie im Voraus.

Nur ein paar Ideen ... die "Macht" Hilfe beschleunigen Dinge in der Serialisierung Bereich.

Bezüglich der Vorgenerierung der Serialisierungsassemblys für Ihre Servicetypen .... gibt es die Option in Project | Build namens "Generate Serialization Assembly" .... wenn sie auf "On" geschaltet ist, dann erzeugt sie die Assemblies bei Bauen Sie Zeit statt zur Laufzeit dynamisch auf.

Es ist nicht klar, ob diese Option nur für die Vorgenerierung von Serialisierungsassemblys für XMLSerializer-basierte Serialisierer oder auch für DataContractSerializers gilt.Sie könnten versuchen, es auf "Ein" zu stellen, um zu sehen, ob es einen Unterschied macht.

Sie könnten auch versuchen, dies frühzeitig im Code in Ihrem Client und Server zu tun, um die DataContract-Serialisierer auszuüben ... d. bevor der Client oder Server eine Anfrage bearbeiten musste ... (nicht sicher, ob es helfen würde oder nicht).

DataContractSerializer ps = new DataContractSerializer(typeof(Person)); 
DataContractSerializer cs = new DataContractSerializer(typeof(Company)); 
etc... 

Um es besser verwaltbar Sie eine Routine schreiben könnte, die Reflexion, die Arten zu finden, verwendet, die Sie zum Beispiel zu serialisiert beabsichtigen Suchen Sie nach Typen, die mit DataContract ... oder einer anderen Heuristik gekennzeichnet sind, oder nach einer vordefinierten Tabelle.

+1

Danke Colin, ich habe alles versucht und nichts davon macht einen Unterschied. Das Problem mit dem letzten Vorschlag besteht darin, dass das Problem, mit dem ich mich beschäftige, ein langsames Starten des Clients ist, so dass es nicht wirklich wichtig ist, ob ich den Start für die Serialisierer mache oder ob das Framework die gleiche Zeit benötigt . Die meisten Kaltstart-Fixes beziehen sich auf die Serverseite, was kein Problem darstellt. Die Option "Serialization Assembly generieren" funktioniert nur für XmlSerializer und nur dann, wenn VS einen Proxy findet (wir haben unseren eigenen). –

+0

Dieser Link könnte Ihnen einige Ideen zu verschiedenen Strategien geben .... http://www.icodeteam.net/default/post/iCodeTeam/35/Object-Serialization-in-NET-Available-serialization-libraries/ –

2

Haben Sie anhand der generierten Servicereferenz bestätigt, dass DataContractSerializer tatsächlich verwendet wird? Es ist möglich, dass aufgrund eines Schemas bei der Operation zum Hinzufügen eines Dienstverweises ein XmlSerializer-Code anstelle des Standard-DataContractSerializers generiert wurde, der dieses für XmlSerializer typische Verhalten verursacht. In diesem Fall können Sie den Serialisierungscode vorgenerieren, um den Kaltstart zu verbessern: http://msdn.microsoft.com/en-us/library/aa751883.aspx. Danke.