protobuf-csharp-port - потоковая передача записей из файла, немного похожая на функцию оси в LINQ-to-XML - PullRequest
1 голос
/ 18 марта 2011

Я создал стандартное учебное пособие по адресной книге, которое поставляется с protobuf-csharp-port, и мой код выглядит следующим образом:

class Program
{
    static void Main(string[] args)
    {
        CreateData();
        ShowData();
    }

    private static void CreateData()
    {
        AddressBook.Builder abb = new AddressBook.Builder();
        for (int i = 0; i < 2000000; i++)
        {
            Person.Builder pb = new Person.Builder();
            pb.Id = i;
            pb.Email = "mytest@thisisatest.com";
            pb.Name = "John" + i;
            abb.AddPerson(pb.Build());
        }
        var ab = abb.Build();
        var fs = File.Create("c:\\testaddressbook.bin");
        ab.WriteTo(fs);
        fs.Close();
        fs.Dispose();
    }

    private static void ShowData()
    {
        var fs = File.Open("c:\\testaddressbook.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
        CodedInputStream cis = CodedInputStream.CreateInstance(fs);
        cis.SetSizeLimit(Int32.MaxValue);
        AddressBook ab = AddressBook.ParseFrom(cis);
        Console.WriteLine("Person count: {0}", ab.PersonCount);
        for (int i = 0; i < ab.PersonCount; i++)
            Console.WriteLine("Name: " + ab.GetPerson(i).Name);
        Console.WriteLine("Person count: {0}", ab.PersonCount);
        fs.Close();
    }
}

При записи данных требуется 300 МБ ОЗУ для записи 2 м.При чтении это занимает около 415 МБ ОЗУ.

В мире XML я бы передавал элементы с помощью функции оси.Можно ли передавать записи внутри объекта модели адресной книги?Или, может быть, есть другой способ реализовать это для более эффективного использования памяти?

спасибо

Ответы [ 2 ]

2 голосов
/ 18 марта 2011

Да, вы можете передавать как чтение, так и запись.

Существует версия, поддерживаемая официальным API Java, а также в моем C # API, с использованием WriteDelimitedTo / ParseDelimitedFrom.

Кроме того, вы можете использовать MessageStreamWriter и MessageStreamIterator, которые я ввел в свой API до появления API с разделителями.

1 голос
/ 18 марта 2011

Я не могу комментировать эту реализацию, но в protobuf-net потоковая передача полностью возможна.Если все объекты, которые вы хотите передать, являются дочерними элементами первого уровня корневого объекта, то вы можете просто выполнить итерацию по внешней последовательности;используя Serializer.DeserializeItems<T>, если они все одного типа, или Serializer.NonGeneric.TryDeaerializeWithLengthPrefix, если задействованы различные типы объектов.

Если элемент, который вы хотите обработать как поток, находится в middle из дерева можно указать альтернативную модель получения;просто реализовав IEnumerable и Add () в поддельной коллекции, он может передавать данные через любой API, который вы хотите (на основе событий, например - SAX).

Следует также отметить, что вы можете сериализовать потоковые данныеточно так же.Не обязательно иметь полную объектную модель в любой момент.

Если вы хотите более полный пример, дайте мне знать.

...