Если OverwriteList
исправляет это, то мне подсказывает *1003*, что в словаре есть некоторые данные по умолчанию, возможно, через конструктор или подобное. Если это действительно исходит от конструктора, вы можете отключить это с помощью [ProtoContract(SkipConstructor=true)]
.
Если я неправильно понял вышеизложенное, это может помочь проиллюстрировать воспроизводимый пример, если это возможно.
Что касается идентификаторов, они должны быть уникальными только внутри каждого типа, и рекомендуется сохранять их небольшими (из-за кодирования тегов «varint» маленькие ключи «дешевле», чем большие).
Если вы действительно хотите минимизировать размер, я бы посоветовал посмотреть и на содержимое данных. Например, вы говорите, что это 15-минутные чтения ... ну, я предполагаю, что есть случайные пробелы, но вы могли бы сделать, например:
Block (class)
Start Time (DateTime)
Values (float[])
и Block
для каждой смежной связки 15-минутных значений (здесь предполагается, что каждое значение равно 15 после последнего, в противном случае запускается новый блок). Таким образом, вы храните несколько Block
экземпляров вместо одного словаря. Это имеет преимущества:
- намного меньше
DateTime
значений для хранения
- вы можете использовать «упакованную» кодировку на поплавках, что означает, что не нужно добавлять все промежуточные теги; Вы делаете это, помечая массив / список как (
[ProtoMember({key}, IsPacked = true)]
) - отмечая, что он работает только с несколькими базовыми типами данных (не подобъектами)
в совокупности эти две настройки могут дать значительную экономию
Если в данных много строк, вы можете попробовать GZIP / DEFLATE. Конечно, вы можете попробовать в любом случае, но без большого количества строковых данных я бы с осторожностью ожидал слишком много дополнительного от сжатия.
В качестве обновления, основанного на прилагаемом файле данных (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; } }
}