MissingMethodException в Protobuf-net (v1) Serializer.Deserialize (.NET CF3.5) и устройство зависает в методе Serializer.DeserializeWithLengthPrefix - PullRequest
1 голос
/ 15 февраля 2012

Я использую Protobuf-net (v1 r282) в приложении .NET CF 3.5 (клиент) и .NET 2.0 WebService.

Существует большое количество данных, которые необходимо отправить между клиентом и сервером (для которых protobuf-net действительно хорош в сокращении времени / объема данных, передаваемых по проводам - ​​сокращает 5-7 минут времени передачи до 25-30 секунд).

Я получаю MissingMethodException после 13-15 вызовов метода Serializer.Deserialize в портативном устройстве (CF 3.5):

StackTrace:

   at ProtoBuf.Property.PropertyFactory.Create[T](MemberInfo member)
   at ProtoBuf.Serializer`1.Build()
   at ProtoBuf.Serializer`1.DeserializeChecked[TCreation](SimpleWrapper& instance, SerializationContext source)
   at ProtoBuf.SerializerSimpleProxy`1.Deserialize(List`1& value, SerializationContext source)
   at ProtoBuf.Serializer.Deserialize[T](SerializationContext source)
   at ProtoBuf.Serializer.Deserialize[T](Stream source)
   at Lazurde.LazurdeDialogs.DLG_9600.DeserializeProtobufData[T](Byte[] protoArray)

Если я попытаюсь использовать метод Serializer.DeserializeWithLengthPrefix , после прибл. столько же звонков аппарат просто зависает . Изменение порядка вызовов (большая десериализация данных сначала или в конце) не имеет значения.

Я использую MemoryStream для процесса сериализации / десериализации.

    public List<T> DeserializeProtobufData<T>(byte[] protoArray)
    {
        List<T> list = null;
        using (var stream = new MemoryStream(protoArray))
        {
            list = Serializer.DeserializeWithLengthPrefix<List<T>>(stream, PrefixStyle.Base128);
            //list = Serializer.Deserialize<List<T>>(stream);
            stream.Close();
        }
        return list ?? new List<T>();
    }

byte [] protoArray , указанный в потоке для самого большого, составляет прибл. 900Kb Данные List<T>, где T - это объекты, содержащие простые типы значений (а также string и DateTime). Объекты указываются как конкретные типы (не интерфейсы) и не имеют никакой иерархии наследования.

Если метод Serializer.Serialize (около 10 вызовов) используется перед десериализацией, Я также иногда получаю исключение OutOfMemory при использовании Serializer.Deserialize после примерно 3-4 вызовов, если сначала используются массивы больших данных, или 7-8, если позже (но не обязательно при десериализации больших данных даже до этого).

Это заставляет меня думать, что в моем приложении есть какая-то утечка памяти, или она использует слишком много mem, или слишком большая фрагментация в куче больших объектов при десериализации с использованием protobuf, но я не могу понять, что он НЕ вылетает и не выдает исключений, когда НЕ использует protobuf-net. (который ждет около 10-15 минут до тех пор, пока не будут переданы данные, для которых использование protobuf меньше минуты.)

Я также пытался использовать GC statemnts, чтобы посмотреть, помогает ли он после каждой десериализации, но, похоже, он не дает никакого эффекта, который заставляет меня думать слишком много о фрагментации с кучей больших объектов.

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Я профилирую память и пытаюсь найти проблемные области, и любая помощь будет высоко оценена. Также будет полезна рекомендация хорошего профилировщика mem для CF 3.5 (в настоящее время используется .NETCF CLR Profiler)

Данные находятся во множестве разных коллекций (приблизительно 15 для отправки клиента на сервер и 20 для отправки сервера клиенту) Размер 3 коллекций (сервер-клиент) составляет около 10000 записей (может увеличиться до 30000 в рабочей среде), причем каждая запись имеет до 45 полей.

Извините за создание такого большого поста, но я подумал, что лучше предоставить больше информации. а не меньше.

Кроме того, есть ли v2 для protobuf-net, доступный для CF3.5? Его нет в z4 r480.

Помощь будет высоко ценится.

1 Ответ

1 голос
/ 15 февраля 2012

Да, MissingMethodException для CF - это королевская PITA , и на самом деле это одна из различных причин, по которой я написал все ядро ​​protobuf-net, по сути, с нуля.

Я верю в этодолжно быть исправлено в v2, так как он не делает никаких общих / неуниверсальных сальто.Если я не строил для CF, то это был просто недосмотр (немного неприятно, но мне нужно использовать разные виртуальные машины для создания версий CF).Он должен собираться из исходного кода, иначе я могу попытаться выполнить сборку CF, когда получу момент.

В отношении любой фрагментации: я бы предпочел не спекулировать на v1, так как мой совет будет "переключиться на v2"и v2 имеет совсем другую кодовую базу.

...