Runtime: Question: Prise en charge de la sérialisation à partir de .Net Core 1.0

Créé le 1 mars 2016  ·  38Commentaires  ·  Source: dotnet/runtime

Salut à tous,
J'ai entendu parler de l'arrêt de la prise en charge de la sérialisation dans .Net Core 1.0 car il n'est pas viable pour la multiplate-forme. (Paraphrasant de mémoire) Qu'est-ce que cela signifie en termes pratiques? Mes bases de code qui utilisent les méthodes Serialize et Deserialize de BinaryFormatter vont-elles être complètement obsolètes, et je devrai convertir ma base de code pour dire, protobuf-net? Ou ai-je mal compris?
Merci,
-Sam

area-Serialization question

Commentaire le plus utile

Voulez-vous que les gens utilisent réellement .NET Core ou est-ce juste une perte de temps comme Silverlight? Si vous voulez que les gens utilisent réellement .NET Core, faites-le fonctionner. Si les gens ont besoin d'une sérialisation, construisez-la - pas de back-talk! Ce sont les personnes qui utilisent réellement votre produit et leur opinion vaut bien plus que la sagesse collective de chaque employé de Microsoft. Vous voyez que ces personnes, contrairement à Microsoft, construisent en fait des éléments critiques sur .NET et si vous voulez que .NET Core soit quelque chose, vous devez arrêter de casser son utilité. Personne ne vous a demandé d'abandonner .NET pour faire une réécriture complète, vous auriez pu simplement porter le framework .NET complet au fil du temps. Vous auriez fini maintenant.

Tous les 38 commentaires

Salut @joshfree , oui, malheureusement, c'est le document qui a causé la confusion. Parmi les suggestions, JSON.NET fait la sérialisation json, protobuf-net fait la sérialisation binaire et datacontractserializer fait la sérialisation xml. Le problème avec ça, c'est si je veux faire une sérialisation binaire. Bien que protobuf-net soit une excellente bibliothèque, elle est limitée. À partir du dépôt Protobuf-nets, les types pris en charge sont:
classes personnalisées qui:
sont marqués comme contrat de données
avoir un constructeur sans paramètre
pour Silverlight: sont publics
de nombreuses primitives communes, etc.
tableaux à une dimension: T []
Liste / IList
Dictionnaire / IDictionary
tout type qui implémente IEnumerable et a une méthode Add (T)
Dans le passé, cela a bien fonctionné car le format binaire a toujours été là, mais ce ne sera plus le cas? Quelle est la méthode recommandée pour la sérialisation binaire des types non pris en charge par protobuf-net? Le construire nous-mêmes?
Je suis encore assez novice dans toutes ces technologies, donc je passe peut-être complètement à côté de quelque chose.

De plus, aucun d'entre eux ne peut sérialiser de manière fiable les exceptions (et conserver toutes les données pertinentes), selon les besoins, par exemple dans l'informatique distribuée (Azure ...).

@cdrnet point est un gros point de friction pour des gars comme les gars d'Orléans IIRC.

Salut @SamuelCox , comme l'a indiqué @joshfree sur le portage, nous (l'équipe de sérialisation) n'avons pas l'intention d'apporter le sérialiseur binaire à .NET Core. Sans .NET à distance et sans concept d'AppDomain dans .NET Core, le sérialiseur binaire est beaucoup moins utile. Veuillez envisager d'autres sérialiseurs dans .NET Core tels que DataContractSerializer (DCS), DataContractJsonSerializer (DCJS) et XmlSerializer, qui sont et continueront d'être pris en charge dans .NET Core. Bien sûr, vous pouvez également envisager des sérialiseurs tiers basés sur .NET Core. Peut-être que je devrais poser la question - recherchez-vous en particulier un sérialiseur qui a une charge utile sérialisée binaire (si oui, pourquoi) ou cherchez-vous simplement un sérialiseur qui peut sérialiser / désérialiser les types qui vous intéressent? Nous nous sommes efforcés de prendre en charge la sérialisation de la plupart des types .NET avec DCS, DCJS et XmlSerializer. N'hésitez pas à nous faire savoir si vous rencontrez des problèmes particuliers et que ces sérialiseurs ne fonctionnent pas pour vous.

@cdrnet et @ RichiCoder1 , merci pour vos commentaires. Il y avait un problème ouvert dotnet / coreclr # 2715 pour la discussion de la sérialisation de l'exception. Veuillez y ajouter vos commentaires. Je conviens qu'il est important de pouvoir sérialiser les exceptions dans un système distribué. Actuellement, sans ISerializable sur .NET Core, nous ne pouvons tout simplement pas sérialiser les exceptions comme nous le faisons dans le framework .NET complet.

Salut @zhenlan , j'aurais peut-être dû le mentionner à l'origine, la principale raison pour laquelle je voudrais un format binaire est de (dé) sérialiser les exceptions et les classes personnalisées qui contiennent des exceptions.

Le cas d'utilisation principal concerne les systèmes distribués, la sérialisation d'un objet dans un tableau d'octets afin que je puisse l'envoyer via tcp / ip. Je me rends compte qu'il est probablement plus courant de sérialiser l'objet en JSON via JSON.NET par exemple, de convertir cette chaîne en un tableau d'octets, de l'envoyer via tcp / ip et d'inverser l'ensemble du processus une fois à l'autre extrémité. Mais cela a beaucoup plus de surcharge que la simple sérialisation vers un tableau d'octets et la désérialisation d'un tableau d'octets vers l'objet souhaité.

Merci @SamuelCox pour la clarification. Je pense que je comprends votre inquiétude maintenant. La sérialisation binaire est un système fermé. Je vous recommande d'envisager d'autres sérialisations basées sur des standards plus ouverts, telles que Xml ou JSON. Vous n'en aurez peut-être pas besoin aujourd'hui, mais cela vous donne plus de flexibilité au cas où vous auriez besoin de prendre en charge la sérialisation entre différentes plates-formes ou avec différents langages / scripts de programmation à l'avenir. Vous ne savez pas quelle sera la taille de vos données, mais si la taille de la charge utile est vraiment un problème, vous pouvez envisager la compression des données, qui est une fonctionnalité intégrée à de nombreux serveurs de nos jours.

Je pensais plus aux frais généraux de la performance qu'à toute autre chose. Cela ressemble à beaucoup d'opérations gaspillées par rapport à la sérialisation et à la désérialisation directement des objets au binaire et inversement. Je pense que je suis heureux de clore cela maintenant car j'ai au moins reçu des éclaircissements. Je pense toujours qu'il y a un écart entre la version 4.6 et le noyau 1.0 qui s'ouvre ici, mais je comprends pourquoi.

Un peu tard dans la conversation, mais voici mes deux cents:

Je pense que ce serait une erreur de croire que l'utilité de BinaryFormatter est limitée à .NET Remoting et AppDomains. Ce qui différencie le BinaryFormatter (obsolète) de ses homologues plus récents, c'est sa capacité à sérialiser les objets .NET les plus exotiques, y compris les fermetures, les sous-types et les graphiques cycliques. Aucun des autres sérialiseurs répertoriés dans le thread actuel n'est capable de faire tout cela. Ce n'est pas un hasard si de nombreux frameworks distribués de pointe, y compris des projets Microsoft tels que Prajna et Mobius (alias SparkCLR), s'appuient sur BinaryFormatter pour fonctionner. Cela n'est pas exclusif au monde .NET: Spark utilise l'ancien et lent sérialiseur binaire Java pour sérialiser les fermetures.

Il existe d'autres sérialiseurs (au format non binaire) qui répliquent les capacités de BinaryFormatter, y compris notre propre bibliothèque FsPickler utilisée par le framework mbrace. Cependant, CoreCLR a déprécié de nombreuses API clés, dans la mesure où je pense que le portage de la bibliothèque vers CoreCLR est une entreprise peu pratique.

D'un point de vue commercial, il serait formidable de voir CoreCLR devenir un concurrent multiplateforme viable de JVM dans le domaine du calcul distribué / big data. Cela ne peut pas se produire sans la plate-forme offrant un support de sérialisation fiable pour les POCO et les fermetures (binaires ou autres).

Voulez-vous que les gens utilisent réellement .NET Core ou est-ce juste une perte de temps comme Silverlight? Si vous voulez que les gens utilisent réellement .NET Core, faites-le fonctionner. Si les gens ont besoin d'une sérialisation, construisez-la - pas de back-talk! Ce sont les personnes qui utilisent réellement votre produit et leur opinion vaut bien plus que la sagesse collective de chaque employé de Microsoft. Vous voyez que ces personnes, contrairement à Microsoft, construisent en fait des éléments critiques sur .NET et si vous voulez que .NET Core soit quelque chose, vous devez arrêter de casser son utilité. Personne ne vous a demandé d'abandonner .NET pour faire une réécriture complète, vous auriez pu simplement porter le framework .NET complet au fil du temps. Vous auriez fini maintenant.

fwiw, CSLA .NET s'appuie sur une sérialisation de haute fidélité car elle repose sur le concept d'objets mobiles.

Lorsque Silverlight est arrivé et qu'il n'avait pas BinaryFormatter ou NetDataContractSerializer, _et_ avait toutes ces limitations de réflexion désagréables, nous avons fini par implémenter notre propre sérialiseur qui utilise une réflexion minimale et ne repose pas sur BF ou NDCS.

Dans un monde post-Silverlight, le problème demeure, car BF / NDCS n'est pas disponible de manière fiable dans UWP, WinRT, .NET Core, etc.

Donc, je pense qu'il y a un argument à faire valoir qu'un sérialiseur de fidélité complète _ devrait_ exister, mais il n'est vraiment utile (au moins imo) que s'il existe sur toutes les différentes incarnations de .NET.

@rockfordlhotka @opinionmachine @eiriktsarpalis Heureux d'entendre plus de gens ressentir la même chose, même si je pense que ce serait plus productif si on le disait un peu plus poliment @opinionmachine , mais chacun à sa place. Comme ce problème est clos, j'imagine que l'équipe corefx ne le surveille plus. Je vous conseillerais de corriger vos préoccupations sur dotnet / coreclr # 2715 comme mentionné par @forki

Je dois admettre que l'abandon de la sérialisation (ainsi que des domaines d'application) était une idée terrible. Je ne pense vraiment pas que cette décision ait été bien réfléchie.

Cependant, ce qui me motive vraiment, c'est que MS n'a pas publié le code nécessaire pour prendre en charge les domaines d'applications, etc. et a laissé à la communauté le soin d'en faire ce qu'elle veut.

Etant donné que coreclr est censé être la version "serveur" de .net, beaucoup de fonctionnalités serveur ont été laissées sur le sol.

Exemple: il a été décidé de laisser StackTrace / StackFrame hors de corefx parce qu'il était "mal utilisé" par certains développeurs, et parce qu'il était rarement utilisé (selon MS). Je crois qu'ils sont revenus à la raison sur celui-là (après une tonne de contrecoup) mais je veux dire vraiment? Qui pense à ce truc?

Pour ce que ça vaut, je suis en fait très satisfait du noyau .net et je pense que c'est un grand pas en avant pour .net, les améliorations de performances sont géniales, il a toujours à peu près toutes les fonctionnalités qui me tiennent à cœur, et c'est multiplateforme. C'est vraiment le seul problème que j'ai avec ça. Il y a beaucoup de valeur à abandonner des fonctionnalités le cas échéant, il suffit de regarder à quel point go a réussi avec son approche minimaliste. Non pas que je dis que .net devrait être aussi minimaliste que possible, ce serait ridicule, je suis personnellement en désaccord avec un design minimaliste, MAIS ce que j'essaie de dire, c'est que MS ne devrait pas être vilipendé pour avoir abandonné certaines fonctionnalités.

@SamuelCox , merci! :-)

Et pour réitérer, les API sont absentes de .NET Core pour de nombreuses raisons. Certains de ces écarts peuvent être facilement corrigés (et nous les corrigeons); certains sont plus difficiles à corriger. Mais nous voulons vous entendre sur les problèmes que vous rencontrez (comme tout cet ensemble de threads sur la sérialisation) et nous voulons trouver un moyen de débloquer vos scénarios.

La sérialisation binaire de graphes d'objets arbitraires, entre les versions d'un même framework est difficile; à travers différents cadres est encore plus difficile. Et par «difficile», je ne veux pas dire qu'il est difficile pour nous de faire le travail. Je veux dire que cela a des implications assez importantes pour d'autres objectifs de la plate-forme (objectifs que je pense que nous partageons tous): sécurité, performance, fiabilité.

Json.NET + TypeNameHandling.All + PreserveReferencesHandling.All + MemberSerialization.Fields vous mène presque tout le chemin. Cependant, il n'y a pas de FormatterServices.GetUninitializedObject, donc un constructeur doit être disponible.

Il n'y a pas de FormatterServices.GetUninitializedObject

C'est le problème central que je pense - les cadres de sérialisation basés sur la réflexion externe peuvent vous aider, mais cette API spécifique doit être là pour permettre l'écriture de ces cadres. Ma recommandation à l'équipe CoreCLR serait de rajouter cette API.

À un moment donné, la communauté .NET (commerciale ou autre) va devoir cesser de compter sur Microsoft lui tenant la main tout le temps. S'il y a une telle exigence pour cela, et que l'on sait depuis un certain temps qu'elle n'est pas disponible, alors pourquoi n'y a-t-il pas eu d'activité communautaire pour proposer une alternative? Json.NET est une alternative communautaire et nous l'utilisons tout le temps. Heck le code source est même disponible sur la source de référence

Cela semble fonctionner pour d'autres plates-formes et je suis sûr que cela fonctionne très bien sur .NET ... à mon avis, c'est une excellente occasion de créer un projet (pour lequel il semble y avoir une demande) et d'obtenir au début de combler ce vide avec des alternatives communautaires

@thecodejunkie que nous aimerions bien, mais nous aurions toujours besoin du runtime pour exposer les API appropriées pour que cela se produise.

FYI: cela fonctionne sur .NET Core: Type appDomainType = Type.GetType("System.AppDomain"); . Et oui, cela vous permet de faire beaucoup de choses ...

Juste pour dire que nous avons amélioré la réactivité de notre serveur frontal de 30%, réduit de 12 cœurs à la charge maximale à 2 cœurs à la charge maximale, réduit la taille du cache redis de 1,7 Go à 350 Mo globalement réduit notre hébergement Azure de 20% (bit plus vraiment)

Vous l'avez deviné BinaryFormatter!

Utilisaient netdatacontractserializer

Je suis venu ici à la recherche de réponses à .Net 4.6.1 étant tellement plus lent avec BinaryFormatter.

Je crois comprendre que ces API reviendront (sérialisation). Bien que ce ne soit pas idéal et présente des problèmes de fragilité, cela devrait au moins permettre au code existant de continuer à fonctionner.

il est également intéressant de concevoir un autre sérialiseur d'objets simple pour le framework de base, un qui est également léger mais qui est plus résilient aux problèmes inter-machines et potentiellement inter-versions

Il existe également des problèmes de sécurité en plus de la fragilité.

@blowdart WRT security, voulez-vous dire des choses comme ça https://blog.scrt.ch/2016/05/12/net-serialiception/?

Ouais, c'est le genre de chose. Tout format de sérialisation qui inclut le type qu'il contient est dangereux, comme Java le découvre cette année. J'étais incroyablement heureux lorsque nous avons abandonné la sérialisation binaire parce que nous avons supprimé toute une classe de vulnérabilités.

@migueldeicaza @blowdart @SamuelCox
Les sérialiseurs sont nécessaires non seulement pour envoyer des choses, mais même in-proc.
Les sérialiseurs binaires, lorsqu'ils sont correctement exécutés, surpassent complètement l'ensemble du tas d'objets natifs lorsqu'il s'agit de stocker des dizaines de millions d'objets en cours de traitement.
Regarde ça:
https://www.infoq.com/articles/Big-Memory-Part-2

Les API de sérialisation sont absolument nécessaires pour une programmation de cluster sensée.
Il est extrêmement gênant de téléporter des instances d'objet CLR -> texte -> CLR, c'est une surcharge énorme.
Ce n'est peut-être pas une erreur de supprimer BinaryFormatter, car il est TRÈS lent et les datagrammes sont énormes, mais
c'était le seul sérialiseur sur le marché en plus de NFX.Slim qui prenait en charge la sémantique de sérialisation CLR complète.
Voir les tableaux détaillés des vitesses et des tailles:
http://aumcode.github.io/serbench/

ISérialisable avec la famille [OnSer / Deser] a beaucoup de sens pour la téléportation en plate-forme.
Ce n'est pas obligatoire, tout comme dans l'ancien NET. Pourquoi ne pas le garder.
Au moins le supporter dans des collections complexes (ie Dictionary), ce n'est pas du tout difficile.

Faire en sorte que tout le monde utilise JSON - est absolument une mauvaise idée car il est plus lent que le sérialiseur binaire (pas BinaryFormatter).
Il semble que tout le monde crée des applications de type Twitter sans logique métier?

@itadapter a une limite à choisir, à savoir que JSON.Net n'est pas le seul jeu de sérialisation en ville. Il y a aussi MsgPack, Protobuf et le propre Bond de Microsoft. (Modifier: votre deuxième lien appelle Protobuf). Json n'est pas la seule option. Il reste cependant le gros problème de la sérialisation des objets .Net avec une sémantique intéressante (Exception).

@ RichiCoder1
Oui bien sûr. Comme on le voit dans les graphiques ci-dessous, c'est-à-dire que JIL est le sérilisateur JSON le plus rapide, mais aucun des sérialiseurs textuels ne peut toucher les sérialiseurs binaires. Protobuf est très rapide au détriment de son incapacité à supporter un vrai polymorphisme et des graphes complexes.

Tout ce que je dis, c'est:

  • Les sérialiseurs binaires sont toujours plus performants pour les objets du domaine métier, en particulier lorsque vous avez beaucoup de données numériques
  • Les sérialiseurs, en général, sont nécessaires NON UNIQUEMENT pour déplacer des données entre des systèmes, mais même à l'intérieur du processus, comme le montre l'approche Big Memory. Ce n'est pas une approche typique, mais cela a beaucoup de sens pratique (c.-à-d. Caches et traversées de graphes sociaux en mémoire)
  • La "téléportation" est une technique similaire à MS Remoting, qui a été honnêtement bâclée. La communication à distance en général lorsqu'elle est bien faite (sans complexité horrible) est TRÈS TRÈS utile dans les systèmes de cluster. Nous utilisons cette approche tout le temps et la programmation est BEAUCOUP plus facile avec des objets natifs - lorsque vous pouvez prendre des objets DOMAIN et simplement les envoyer à une autre méthode telle quelle, que ce soit sur cette machine ou sur une machine adjacente dans le rack

Benchmarks d'une "personne typique", montrant les sérialiseurs populaires:
http://aumcode.github.io/serbench/Specimens_Typical_Person/web/overview-charts.htm

Juste au cas où quelqu'un sur ce thread ne serait pas au courant, un sérialiseur binaire, y compris ISerializable, etc. a été rendu disponible dans corefx
https://github.com/dotnet/corefx/tree/master/src/System.Runtime.Serialization.Formatters

@zhenlan Une partie du travail .NetStandard2.0 je suppose?

@ RichiCoder1 Oui, c'est correct.

@zhenlan est super!

@zhenlan Je n'arrive pas à trouver l'attribut sérialisable disponible dans l'aperçu de Standard. Suis-je juste en train de le manquer?

@justinhelgerson devrait être là.

Avez-vous installé le SDK 2.0 Preview1 comme indiqué dans le billet de blog d'annonce ?

Après avoir créé un projet .NET Core, pouvez-vous vous assurer que le fichier .csproj contient <TargetFramework>netstandard2.0</TargetFramework> si vous avez créé une bibliothèque de classes ou <TargetFramework>netcoreapp2.0</TargetFramework> si vous avez créé une application console?

BTW, étant donné que de nombreux utilisateurs de ce fil sont intéressés par le sérialiseur binaire, vous pourriez être intéressé par une discussion dans dotnet / corefx # 19119, qui concerne la réduction de [Serializable] pour .NET Core 2.0. Veuillez nous le faire savoir au cas où vous auriez des commentaires.

@zhenlan Merci beaucoup pour votre réponse rapide. J'avais installé l'aperçu via NuGet mais je n'ai pas mis à jour manuellement mon fichier .csproj. Cela a fait l'affaire! Je vais lire sur la réduction et fournir des informations si cela aurait un impact sur notre cas d'utilisation.

@justinhelgerson , les modifications de

Cette page vous a été utile?
0 / 5 - 0 notes