C# Protobuf net v2和大型词典
我有一个奇怪的情况发生,我不太明白 我有一个“dataset”类,它保存关于监测浮标的各种元数据,包括“传感器”列表 每个当前“传感器状态” 每个“sensorstate”都有一些元数据(时间戳、更改原因等),但最重要的是,它有一个C# Protobuf net v2和大型词典,c#,.net-4.0,protobuf-net,C#,.net 4.0,Protobuf Net,我有一个奇怪的情况发生,我不太明白 我有一个“dataset”类,它保存关于监测浮标的各种元数据,包括“传感器”列表 每个当前“传感器状态” 每个“sensorstate”都有一些元数据(时间戳、更改原因等),但最重要的是,它有一个字典 这些传感器通常有超过50k个数据点(相当于15分钟的数据读取时间),因此我想找到比默认的.NETBinaryFormatter更快的序列化方法,并设置一个可以非常快地序列化的设置 不幸的是,当我的值字典抛出一个异常时,反序列化出现了我的问题,因为已经有一个添加了
字典
这些传感器通常有超过50k个数据点(相当于15分钟的数据读取时间),因此我想找到比默认的.NETBinaryFormatter
更快的序列化方法,并设置一个可以非常快地序列化的设置
不幸的是,当我的值字典抛出一个异常时,反序列化出现了我的问题,因为已经有一个添加了相同键的项,我唯一能让它反序列化的方法是启用“OverwriteList”,但我有点不确定为什么在序列化时没有任何重复键(这是一个字典),那么,为什么在反序列化时会有重复的键呢?这也带来了数据完整性问题
如果您能帮助解释这一点,我们将不胜感激
(另一方面,当给出ProtoMember属性ID时,它们是否需要对类或整个项目唯一?我正在寻找无损压缩建议,以便与protobuf net结合使用,因为文件越来越大)
编辑:
我刚刚在GitHub上发布了我的源代码,下面是有问题的类
(注意:为了使其能用于其他开发,它当前的OverwriteList=true)
这里有一个例子
我已经尝试使用SkipContractor标志,但即使将其设置为true,也会出现异常,除非OverwriteList对于值字典也是true。如果
OverwriteList
修复了它,那么它向我建议字典默认情况下包含一些数据,可能是通过构造函数或类似方法。如果它确实来自构造函数,您可以使用[ProtoContract(SkipConstructor=true)]
禁用它
如果我误解了上述内容,如果可能的话,可以用一个可复制的例子来说明
关于ID,它们只需要在每种类型中都是唯一的,并且建议保持它们的小型化(由于标记的“可变”编码,小型键比大型键“便宜”)
如果你真的想最小化数据的大小,我建议你也看看数据的内容。例如,你说这是15分钟的阅读。。。嗯,我猜偶尔会有间隙,但你能做些什么,例如:
Block (class)
Start Time (DateTime)
Values (float[])
对于每一个连续的15分钟值串,都有一个块
(这里的假设是,每个值都是最后一个值之后的15,否则会启动一个新块)。因此,您正在存储多个块
实例来代替单个字典。这有以下优点:
- 要存储的
值少得多DateTime
- 您可以在浮动上使用“打包”编码,这意味着不需要添加所有中间标记;您可以通过将数组/列表标记为(
)来实现这一点,注意它只适用于少数基本数据类型(而不是子对象)[ProtoMember({key},IsPacked=true)]
作为基于提供的(CSV)数据文件的更新,在处理字典时没有固有的问题-如图所示:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ProtoBuf;
class Program
{
static void Main()
{
var data = new Data
{
Points =
{
{new DateTime(2009,09,1,0,0,0), 11.04F},
{new DateTime(2009,09,1,0,15,0), 11.04F},
{new DateTime(2009,09,1,0,30,0), 11.01F},
{new DateTime(2009,09,1,0,45,0), 11.01F},
{new DateTime(2009,09,1,1,0,0), 11F},
{new DateTime(2009,09,1,1,15,0), 10.98F},
{new DateTime(2009,09,1,1,30,0), 10.98F},
{new DateTime(2009,09,1,1,45,0), 10.92F},
{new DateTime(2009,09,1,2,00,0), 10.09F},
}
};
var ms = new MemoryStream();
Serializer.Serialize(ms, data);
ms.Position = 0;
var clone =Serializer.Deserialize<Data>(ms);
Console.WriteLine("{0} points:", clone.Points.Count);
foreach(var pair in clone.Points.OrderBy(x => x.Key))
{
float orig;
data.Points.TryGetValue(pair.Key, out orig);
Console.WriteLine("{0}: {1}", pair.Key, pair.Value == orig ? "correct" : "FAIL");
}
}
}
[ProtoContract]
class Data
{
private readonly Dictionary<DateTime, float> points = new Dictionary<DateTime, float>();
[ProtoMember(1)]
public Dictionary<DateTime, float> Points { get { return points; } }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Linq;
使用ProtoBuf;
班级计划
{
静态void Main()
{
var数据=新数据
{
要点=
{
{新日期时间(2009,09,1,0,0,0),11.04F},
{新日期时间(2009,09,1,0,15,0),11.04F},
{新日期时间(2009,09,1,0,30,0),11.01F},
{新日期时间(2009,09,1,0,45,0),11.01F},
{新日期时间(2009,09,1,1,0,0),11F},
{新日期时间(2009,09,1,1,15,0),10.98F},
{新日期时间(2009,09,1,1,30,0),10.98F},
{新日期时间(2009,09,1,1,45,0),10.92F},
{新日期时间(2009,09,1,2,00,0),10.09F},
}
};
var ms=新内存流();
序列化器。序列化(ms、数据);
ms.Position=0;
var clone=序列化程序。反序列化(ms);
WriteLine(“{0}点:”,clone.points.Count);
foreach(clone.Points.OrderBy(x=>x.Key)中的变量对)
{
浮动原点;
data.Points.TryGetValue(pair.Key,out-orig);
Console.WriteLine(“{0}:{1}”,pair.Key,pair.Value==orig?”正确:“FAIL”);
}
}
}
[原始合同]
类数据
{
私有只读字典点=新字典();
[原成员(1)]
公共字典点{get{return Points;}}
}
这是我道歉的地方,因为我曾经暗示它与我自己没有做过的代码有关。而当我在这里为protobuf和Marc Gravell背后的protobuf net团队提供疯狂道具时,它真的很快
发生的事情是在类中,我有一些逻辑,从不让两个属性为空
[ProtoMember(12)]
public SensorState CurrentState
{
get { return (_currentState == null) ? RawData : _currentState; }
set { _currentState = value; }
}
我已经设置了[ProtoContract(SkipConstructor=true)],但问题仍然存在,我已经更新了我的帖子,链接到源代码并提供了原始数据文件。我的问题完全是我自己的,很抱歉,甚至暗示了其他问题:)嗨;我对SensorState进行了简要的介绍,但它并不是处于“最小”状态,我实际上可以跳入并复制任何内容(我尝试添加越来越多的文件以使其进行编译,但没有成功)。我在下面添加了一个最小的示例(处理提供的数据),sh
[ProtoMember(16)]
public SensorState RawData
{
get { return _rawData ?? (_rawData = new SensorState(this, DateTime.Now, new Dictionary<DateTime, float>(), "", true, null)); }
private set { _rawData = value; }
}
[ProtoMember(16)]
private SensorState _rawData;
[ProtoMember(12)]
private SensorState _currentState;