2012-01-16 2 views
5

У меня есть приложение C#, которое необходимо десериализовать много тысяч сообщений protobuf в секунду. В интересах избежать ненужных коллекций мусора, мне интересно, есть ли способ использовать предварительно выделенную память, чтобы каждая операция десериализации не требовала выделения новой памяти.Используя protobuf-net, можно ли десериализовать сообщение без выделения памяти?

Что я предвижу, так это то, что я выделил пул объектов сообщения перед выполнением, а затем проинструктирует протобуф-код использовать следующее доступное сообщение из этого пула для каждой десериализации.

Существует ли эта функциональность или есть ли другой способ оптимизации использования памяти в этом сценарии?

Спасибо!

+2

Вы определили, что это на самом деле проблема? Вы столкнулись с этим сценарием, когда вы используете приложение, либо работающее на низком уровне памяти, либо работающее медленно из-за сборов мусора? – BFree

+0

Нет, но это единственная область кода в этой высокочастотной компоненте, которая в настоящее время требуется для распределения памяти, поэтому мне представляется целесообразным изучить возможность ее устранения, особенно если есть простой подход. – newdayrising

+0

Распределение и сбор мусора объектов, которые недолговечны, чрезвычайно быстры.Вы, вероятно, не должны беспокоиться об этом, если вы действительно не профилируете свой код и не узнаете, что это узкое место. – svick

ответ

10

Да, есть! Внутри он уже использует микро-пул, чтобы избежать выделения слишком большого количества рабочих буферов, но если вы пропустили достаточно объектов, которые являются проблемой GC, вы можете использовать свою собственную схему распределения и создать фабрику пользовательских объектов; это не может быть определено на атрибутов в настоящее время, но могут быть применены с помощью типа-модели:

RuntimeTypeModel.Default.Add(typeof (Foo), true).SetFactory(factory); 

, где factory либо:

  • имя метода static на Foo (т.е. "CreateFoo"), который возвращает Foo
  • MethodInfo любого метода static (не требуется быть Foo), которая возвращает Foo

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

public static Foo CreateFoo() { 
    return GetFromYourOwnMicroPool(); 
} 

Обратите внимание, что в этом использовании, ожидается, что завод будет сбрасывать объект в состояние ванили; protobuf-net не будет пытаться это сделать. Обратите также внимание на то, что в настоящее время protobuf-net не представляет микрокомпьютер в качестве повторно используемого компонента, но вы можете повторно использовать источник достаточно легко.

Эта функция была специально добавлена ​​для поддержки пользователей с очень высокой пропускной способностью, который хотел, чтобы удалить даже малейшие GC накладные расходы (на основе большого количества измерений ... они послали мне довольно графики и все, p)

Дополнительно : , за исключением корневого объекта, protobuf-net поддерживает struct значения без бокса; поэтому, если у вас есть сложная/вложенная объектная модель, другая опция в крайних случаях - это посмотреть на struct s.

+0

Можете ли вы прояснить, как использовать структуры? Можем ли мы это сделать при генерации из прото-файла? Как насчет этого утверждения в github readme? 'Код предполагает, что типы будут изменяться вокруг избранных членов. Соответственно, пользовательские структуры не поддерживаются, так как они должны быть неизменными. « – Aranda

+0

@ Аранда это замечание может предусматривать поддержку структур. Инструмент генерации только испускает классы на данный момент, но структуры должны работать нормально. –

+0

Спасибо, Марк. Я начал работать, вручную отредактировав сгенерированные классы как структуры (для типов, отличных от root), но не смог устранить все распределения, поскольку как подход на заводе, так и метод слияния, похоже, не устраняли распределение корневых типов. На данный момент мы тестируем коммутатор на Flatbuffers. – Aranda

Смежные вопросы