gpt4 book ai didi

c# - 通过序列化对象列表进行奇怪的 Protobuf 加速

转载 作者:太空宇宙 更新时间:2023-11-03 12:29:47 29 4
gpt4 key购买 nike

我发现 ProtoBuf 性能有一个非常奇怪的问题,涉及大量复杂对象的序列化。让我们有这两种情况:

A) 逐一序列化对象列表

B) 序列化整个列表

凭直觉,这应该具有相似的性能。但是,在我的应用程序中,仅通过将对象放入列表并序列化列表,反序列化就有 10 倍的差异。您可以在下面找到代码来测试它。在此示例中,结果在 2 倍和 5 倍加速之间变化,但在我的代码中,它的 10 倍加速非常一致。

这是什么原因造成的?我有一个应用程序,我需要一个一个地序列化对象,它确实降低了性能,有什么方法可以提高一个一个地序列化的性能 ?

谢谢

代码输出如下

One by one serialization = 329204 ; deserialization = 41342
List serialization = 19531 ; deserialization = 27716

代码

[ProtoContract]
class TestObject
{
[ProtoMember(1)]public string str1;
[ProtoMember(2)]public string str2;
[ProtoMember(3)]public int i1;
[ProtoMember(4)]public int i2;
[ProtoMember(5)]public double d1;
[ProtoMember(6)]public double d2;
public TestObject(int cnt)
{
str1 = $"Hello World {cnt}";
str2 = $"Lorem ipsum {cnt}";
for (int i = 0; i < 2 ; i++) str1 = str1 + str1;
d1 = i1 = cnt;
d2 = i2 = cnt * 2;
}
public TestObject() { }
}
private void ProtoBufTest()
{
//init test data
List<TestObject> objects = new List<TestObject>();
int numObjects = 1000;
for(int i = 0; i < numObjects;i++)
{
objects.Add(new TestObject(i));
}
Stopwatch sw = new Stopwatch();
MemoryStream memStream = new MemoryStream();

//test 1
sw.Restart();
for (int i = 0; i < numObjects; i++)
{
ProtoBuf.Serializer.SerializeWithLengthPrefix<TestObject>(memStream, objects[i], ProtoBuf.PrefixStyle.Base128);
}
long timeToSerializeSeparately = sw.ElapsedTicks;
memStream.Position = 0;

sw.Restart();
for (int i = 0; i < numObjects; i++)
{
ProtoBuf.Serializer.DeserializeWithLengthPrefix<TestObject>(memStream, ProtoBuf.PrefixStyle.Base128);
}
long timeToDeserializeSeparately = sw.ElapsedTicks;

//test 2
memStream.Position = 0;
sw.Restart();
ProtoBuf.Serializer.SerializeWithLengthPrefix<List<TestObject>>(memStream, objects, ProtoBuf.PrefixStyle.Base128);
long timeToSerializeList = sw.ElapsedTicks;

memStream.Position = 0;
sw.Restart();
ProtoBuf.Serializer.DeserializeWithLengthPrefix<List<TestObject>>(memStream, ProtoBuf.PrefixStyle.Base128);
long timeToDeserializeList = sw.ElapsedTicks;

Console.WriteLine($"One by one serialization = {timeToSerializeSeparately} ; deserialization = {timeToDeserializeSeparately}");
Console.WriteLine($"List serialization = {timeToSerializeList} ; deserialization = {timeToDeserializeList}");
}

最佳答案

我认为您歪曲了初始反射预处理和 JIT 成本;如果我们更改它以便它多次运行测试:

static void Main()
{
ProtoBufTest(1);
for (int i = 0; i < 10; i++)
{
ProtoBufTest(1000);
}
}

private static void ProtoBufTest(int numObjects)
{
...

然后我得到了我期望的结果,其中单个对象代码更快

基本上,它会在第一次需要时做很多的工作,基本上正是您在这里要求的:

is there some way to force ProtoBuf to cache reflection data between calls ? That would help a lot probably

已经发生了。作为旁注,您还可以:

    Serializer.PrepareSerializer<TestObject>();

一旦在您的应用程序开始时,它将尽可能多地执行。不过,我不能强制执行 JIT - 为此,您需要调用一次代码。

关于c# - 通过序列化对象列表进行奇怪的 Protobuf 加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43209521/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com