Почему десериализатор protobuf-net намного медленнее в моем коде, чем потоковое чтение csv - PullRequest
2 голосов
/ 31 января 2012

Я храню простые временные ряды в следующем формате и ищу самый быстрый способ прочитать и проанализировать их, чтобы "процитировать" объекты:

DateTime, цена1, цена2 , , , DateTime имеет следующий формат строки: ГГГГммдд ЧЧ: мм: сс: fff цена1 и цена 2 - это строки чисел с 5 десятичными разрядами (1.40505, т.е.)

Я играл разными способами для хранения и чтения данных, а также играл с библиотекой protobuf-net. Файл, который был сериализован и содержал примерно 6 миллионов строк (raw csv сериализовался следующим образом:

объект TimeSeries, содержащий List<Blobs>, Blob-объект, содержащий объект Header и List<Quotes> (один BLOB-объект содержит кавычки на один день) Объект кавычки, содержащий DateTime, двойной px1 и двойной px2

Потребовалось около 47 секунд, чтобы прочитать (с диска) сериализованный двоичный файл и десериализовать его, что выглядело ужасно долго. В отличие от этого, я держал временные ряды в формате строки CSV, читал каждую строку в список, а затем анализировал каждую строку в DateTime dt, double px1, double px1, которые я вставил во вновь созданный объект Quote и добавил их в список. Чтение заняло около 10 секунд (12 секунд при сжатии GZip -> создание файла размером примерно 1/9 размера.)

На первый взгляд мне кажется, что я либо неправильно работаю с протоколом protobuf-net, либо этот конкретный тип временных рядов плохо подходит для сериализации / десериализации.

Любые комментарии или помощь, особенно Марк, если вы прочитаете это, не могли бы вы присоединиться и добавить некоторые свои мысли? Мне трудно представить, что я получаю такие разные показатели производительности.

Некоторая информация: мне не нужен произвольный доступ к данным. Мне нужно только читать полные дни, поэтому хранение данных за один день в отдельном CSV-файле имело смысл для моей цели, подумала я.

Есть идеи, что может быть самым быстрым способом чтения таких данных? Прошу прощения за упрощенный язык, я не программист наизусть.

Вот пример объекта, который я использую для protobuf-net:

[ProtoContract]
class TimeSeries
{
    [ProtoMember(1)]
    public Header Header { get; set; }
    [ProtoMember(2)]
    public List<DataBlob> DataBlobs { get; set; }
}

[ProtoContract]
class DataBlob
{
    [ProtoMember(1)]
    public Header Header { get; set; }
    [ProtoMember(2)]
    public List<Quote> Quotes { get; set; }
}

[ProtoContract]
class Header
{
    [ProtoMember(1)]
    public string SymbolID { get; set; }
    [ProtoMember(2)]
    public DateTime StartDateTime { get; set; }
    [ProtoMember(3)]
    public DateTime EndDateTime { get; set; }
}

[ProtoContract]
class Quote
{
    [ProtoMember(1)]
    public DateTime DateTime { get; set; }
    [ProtoMember(2)]
    public double BidPrice { get; set; }
    [ProtoMember(3)]
    public long AskPrice { get; set; } //Expressed as Spread to BidPrice
}

Вот код, используемый для сериализации / десериализации:

public static void SerializeAll(string fileNameWrite, List<Quote> QuoteList)
    {
        //Header
        Header Header = new Header();
        Header.SymbolID = SymbolID;
        Header.StartDateTime = StartDateTime;
        Header.EndDateTime = EndDateTime;

        //Blob
        List<DataBlob> DataBlobs = new List<DataBlob>();
        DataBlob DataBlob = new DataBlob();
        DataBlob.Header = Header;
        DataBlob.Quotes = QuoteList;
        DataBlobs.Add(DataBlob);

        //Create TimeSeries
        TimeSeries TimeSeries = new TimeSeries();
        TimeSeries.Header = Header;
        TimeSeries.DataBlobs = DataBlobs;

        using (var file = File.Create(fileNameWrite))
        {
            Serializer.Serialize(file, TimeSeries);
        }
    }

public static TimeSeries DeserializeAll(string fileNameBinRead)
    {
        TimeSeries TimeSeries;

        using (var file = File.OpenRead(fileNameBinRead))
        {
            TimeSeries = Serializer.Deserialize<TimeSeries>(file);
        }

        return TimeSeries;
    }

1 Ответ

4 голосов
/ 31 января 2012

Самым быстрым способом является двоичный сериализатор с ручным кодированием, особенно если вы преобразуете тики пиков.Это то, что я делаю, хотя мой объем немного отличается (600 миллионов предметов в день, около 200 000 символов, причем некоторые из них являются самыми тяжелыми).Я ничего не храню таким образом, который требует анализа текста.Parser - ручная работа, и я использую профилировщик, чтобы оптимизировать его - aos очень хорошо справляется с размером (иногда торговля уменьшается до 1 байта).

...