我编写了一个程序来使用XMLSerializer,BinaryFormatter和ProtoBuf序列化一个'Person'类.我认为protobuf-net应该比其他两个更快.Protobuf序列化比XMLSerialization更快,但比二进制序列化慢得多.我的理解不正确吗?请让我明白这一点.感谢您的帮助.
编辑: - 我更改了代码(下面更新)来测量仅序列化的时间,而不是创建流,仍然看到差异.能告诉我为什么吗?
以下是输出: -
人在347毫秒内使用协议缓冲区创建
人在1462毫秒内使用XML创建
人在2毫秒内使用二进制创建
代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
namespace ProtocolBuffers
{
class Program
{
static void Main(string[] args)
{
string folderPath = @"E:\Ashish\Research\VS Solutions\ProtocolBuffers\ProtocolBuffer1\bin\Debug";
string XMLSerializedFileName = Path.Combine(folderPath,"PersonXMLSerialized.xml");
string ProtocolBufferFileName = Path.Combine(folderPath,"PersonProtocalBuffer.bin");
string BinarySerializedFileName = Path.Combine(folderPath,"PersonBinary.bin");
if (File.Exists(XMLSerializedFileName))
{
File.Delete(XMLSerializedFileName);
Console.WriteLine(XMLSerializedFileName + " deleted");
}
if (File.Exists(ProtocolBufferFileName))
{
File.Delete(ProtocolBufferFileName);
Console.WriteLine(ProtocolBufferFileName + " deleted");
}
if (File.Exists(BinarySerializedFileName))
{
File.Delete(BinarySerializedFileName);
Console.WriteLine(BinarySerializedFileName + " …Run Code Online (Sandbox Code Playgroud) 我正在实现客户端 - 服务器应用程序,并正在研究序列化和传输数据的各种方法.我开始使用Xml Serializers,它工作得很好,但是生成数据很慢,并且生成大对象,特别是当它们需要通过网络发送时.所以我开始研究Protobuf和protobuf-net.
我的问题在于protobuf没有发送类型信息.使用Xml Serializers,我能够构建一个包装器,它将在同一个流上发送和接收任何各种(可序列化的)对象,因为序列化为Xml的对象包含对象的类型名称.
ObjectSocket socket = new ObjectSocket();
socket.AddTypeHandler(typeof(string)); // Tells the socket the types
socket.AddTypeHandler(typeof(int)); // of objects we will want
socket.AddTypeHandler(typeof(bool)); // to send and receive.
socket.AddTypeHandler(typeof(Person)); // When it gets data, it looks for
socket.AddTypeHandler(typeof(Address)); // these types in the Xml, then uses
// the appropriate serializer.
socket.Connect(_host, _port);
socket.Send(new Person() { ... });
socket.Send(new Address() { ... });
...
Object o = socket.Read();
Type oType = o.GetType();
if (oType == typeof(Person))
HandlePerson(o as …Run Code Online (Sandbox Code Playgroud) 由于ProtoBuf-Net不支持序列化/反序列化多维数组,我将如何管理我的数组呢?
我想尝试将一个Protobuf ValueProviderFactory添加到MVC3,以便我可以选择MIME类型并将原始数据反序列化为对象以获取操作参数.我也可以使用它来更改默认的Json序列化程序.
看JsonValueProviderFactory.cs这个应该不会太难,但工厂似乎都是硬编码的.
对于Protobuf我可以用IValueProvider做一些事情,但我还没有检查MVC3在收到MIME类型时做了什么application/x-protobuf.
我是以正确的方式来做这件事的吗?
UPDATE
我发现这个博客文章谈论创建一个IValueProvider.然后它在底部提到这改变了MCV2.他将其改为a ValueProviderFactory并致电:
ValueProviderFactories.Factories.Add(new HttpCookieValueProviderFactory());
Run Code Online (Sandbox Code Playgroud)
但在MVC3中,此属性是只读的.
尝试使用protobuf.net反序列化对象时,有时会收到以下异常.我很惊讶,因为我从来没有多个线程同时反序列化同一个对象,并且protobuf.net源似乎没有使用任何静态对象进行反序列化.例外确实提出了一个解决方案,但我不确定如何实现,所以欢迎一个例子.
Base Exception Type:
System.TimeoutException: Timeout while inspecting metadata; this may indicate a deadlock. This can often be avoided by preparing necessary serializers during application initialization, rather than allowing multiple threads to perform the initial metadata inspection
at ProtoBuf.Meta.RuntimeTypeModel.TakeLock(Boolean& lockTaken)
at ProtoBuf.Meta.RuntimeTypeModel.FindOrAddAuto(Type type, Boolean demand, Boolean addWithContractOnly, Boolean addEvenIfAutoDisabled)
at ProtoBuf.Meta.RuntimeTypeModel.GetKey(Type type, Boolean demand, Boolean getBaseKey)
Inner Exception Type:
System.TimeoutException: Timeout while inspecting metadata; this may indicate a deadlock. This can often be avoided by preparing necessary serializers …Run Code Online (Sandbox Code Playgroud) Protobuf-net中存在AsReference选项,而BinaryFormatter是一个"图形序列化器",这使我认为BinaryFormatter不维护引用,并且它会复制每个对象.
但我做了一些测试,发现即使对于递归引用,单个BinaryFormatter Serialize()或Deserialize()调用中的所有引用都会被维护.
我可以确认BinaryFormatter确实维护引用吗?这与Protobuf-net有何不同?好像我理解"图形序列化"不正确?我还应该注意什么?
提前致谢.
在我们的应用程序中,我们有一些数据结构,其中包含一个分块的字节列表(当前公开为a List<byte[]>).我们将字节大块化,因为如果我们允许将字节数组放在大对象堆上,那么随着时间的推移,我们会遇到内存碎片.
我们也开始使用Protobuf-net来序列化这些结构,使用我们自己生成的序列化DLL.
但是我们注意到Protobuf-net在序列化时会创建非常大的内存缓冲区.浏览源代码看起来似乎它可能无法刷新其内部缓冲区,直到整个List<byte[]>结构被写入,因为它需要在缓冲区前面写入总长度.
不幸的是,这首先解决了我们的工作,首先将字节分块,最终由于内存碎片而给我们OutOfMemoryExceptions(异常发生在Protobuf-net尝试将缓冲区扩展到84k以上时,这显然是在LOH,我们的整体进程内存使用率相当低.
如果我对Protobuf-net如何工作的分析是正确的,那么有没有解决这个问题的方法呢?
更新
根据Marc的回答,这是我尝试过的:
[ProtoContract]
[ProtoInclude(1, typeof(A), DataFormat = DataFormat.Group)]
public class ABase
{
}
[ProtoContract]
public class A : ABase
{
[ProtoMember(1, DataFormat = DataFormat.Group)]
public B B
{
get;
set;
}
}
[ProtoContract]
public class B
{
[ProtoMember(1, DataFormat = DataFormat.Group)]
public List<byte[]> Data
{
get;
set;
}
}
Run Code Online (Sandbox Code Playgroud)
然后序列化它:
var a = new A();
var b = new B();
a.B = b;
b.Data = new List<byte[]>
{
Enumerable.Range(0, 1999).Select(v => …Run Code Online (Sandbox Code Playgroud) 我们在.NET中有一些(很多)类.我们使用protobuf-net来标记它们,并通过谷歌原始库为C++代码端生成.proto包装器.
所以我有一条消息(C++ DebugString()在一些EventBase类上(在.NET中EventCharacterMoved 继承,EventBase而在C++中我只是写入可选属性)):
UserId: -2792
EventCharacterMoved {
Coordinates {
Position {
X: 196.41913
Y: 130
Z: 213
}
Rotation {
X: 207
Y: 130
Z: 213
}
}
OldCoordinates {
Position {
X: 196.41913
Y: 130
Z: 213
}
Rotation {
X: 207
Y: 130
Z: 213
}
}
}
Run Code Online (Sandbox Code Playgroud)
(来自这样的.proto文件)
message Coordinates {
optional TreeFloat Position = 1;
optional TreeFloat Rotation = 2;
}
message EventBase {
optional int32 UserId = …Run Code Online (Sandbox Code Playgroud) 我正在开发一个包含Client/Server的项目.客户端是用Python编写的(将在linux上运行)和C#中的服务器.我正在通过标准套接字进行通信,我正在使用protobuf-net进行协议定义.但是,我想知道protobuf-net如何处理DateTime序列化.Unix日期时间与.net标准日期时间不同,那么我该如何处理这种情况呢?
谢谢
我指定了许多独立的gRPC服务,这些服务都将在同一服务器进程中托管.每个服务都在自己的protobuf文件中定义.然后通过gRPC工具运行这些工具,为我提供目标语言(在我的情况下为c#),然后我可以在其中实现我的服务器和客户端.
每个这些不同的API使用一些共同的元素,诸如错误响应枚举,该空消息类型(这似乎是在可用GRPC WellKnownTypes ;但我不能看我怎么有,要么让我定义我自己).
目前,我最终将每个proto构建重复的枚举和类放入他们自己的命名空间中.虽然我知道我可以在一个共同的原型文件中共享这些定义并包含它; 我不知道如何只将这些代码生成一个共同的命名空间.虽然这是有效的,但将它保持在一组是最整洁的; 如果在服务之间聚合错误等事情,它在转换和等效性方面也可能会出现问题.
我假设我遗漏了一些东西,因为我对WellKnownTypes命名空间这样的东西的阅读表明这应该是可能的,但如前所述,我也没有看到我在Proto中如何引用它.
因此目前在gRPC上似乎相当轻松,所以我的搜索量不会太多,我是新手,所以任何指针?