Недавно я провел некоторое тестирование производительности и анализа приложения ASP.NET с использованием состояния сеанса вне процесса - это необходимо при использовании состояния сеанса в веб-ферме, чтобы состояние можно было восстановить на любой из веб-серверов, например если последующие HTTP-запросы поступают на другой сервер, потому что сеансы не «липкие» или исходный сервер не работает и т. д.Возможные решения для плохой производительности сериализации
Что меня удивило, когда я запускал веб-серверы при полной загрузке и профилировал использование ЦП что-то вроде 99% процессорного времени было потрачено на сериализацию и десериализацию состояния сеанса. Впоследствии мы реализовали настраиваемый государственный сервер «кэширования»; это всегда сериализует состояние, но также сохраняет состояние в памяти, так что, если вы используете липкие сеансы, состояние не нужно десериализовать большую часть времени. Это улучшило пропускную способность сервера в 2 раза; Однако сериализация по-прежнему составляет 98% или более времени процессора.
Мы получили некоторые дополнительные улучшения скорости путем «обрезки» ненужных ссылок на объекты между объектами в состоянии сеанса перед сериализацией - исправление ссылок вручную при десриализации. Это улучшило скорость еще на 10-20% или около того. Примером здесь является то, что некоторые потери производительности связаны с тем, что встроенная сериализация должна идти по графику указателей объектов, что становится более сложной задачей с большим количеством указателей.
Продолжая исследование, мы написали индивидуальные процедуры сериализации для некоторых наших классов, а не полагаемся на встроенную сериализацию .Net. Мы обнаружили, что производительность была значительно улучшена, примерно в 50x. Похоже, что основная часть загрузки ЦП обусловлена встроенной сериализацией .Net, которая, в свою очередь, медленна из-за использования использования Reflection для перемещения указателей/графиков объектов и извлечения данных поля.
Это очень заманчиво увеличить нашу производительность на 50 раз, таким образом уменьшая требования к аппаратным средствам веб-сервера с большим коэффициентом (и потребностями в энергии меньшим, но все же значительным фактором). Возможные варианты:
1) Напишите индивидуальную сериализацию. Это проблема из-за сложности задачи и затрат на обслуживание, которые она генерирует, то есть любые изменения состояния класса требуют изменения в процедурах сериализации/десериализации.
2) Некоторые сторонние решения. Возможно, какой-то продукт, который автоматически генерирует код сохранения состояния/загрузки во время сборки, тем самым устраняя необходимость использования Reflection.
Мне было бы очень интересно узнать, знает ли кто-нибудь о стороннем решении, или столкнулся с этой проблемой, поскольку я не нашел упоминания об этом из интернет-поиска.
ОБНОВЛЕНИЕ: Некоторые из них предложили своего рода решение на полпути между встроенной сериализацией по умолчанию и чистыми настраиваемыми процедурами сериализации. Идея заключается в том, что вы реализуете персонализированную сериализацию для классов, которые влияют на производительность больше всего, например. преодолевая ISerializable. Это интересный и многообещающий подход; Однако я по-прежнему считаю, что есть возможности для полной замены встроенной сериализации без необходимости писать и поддерживать какой-либо пользовательский код - это невозможно сделать во время выполнения, потому что Reflection необходим для запроса объектов и доступа к личным данным. Но теоретически возможно послепродавать уже построенные сборки и внедрять новые методы в качестве дополнительного шага сборки. Некоторые профилировщики используют этот подход для ввода кода профилирования в сборки после того, как они были созданы компилятором C#. Также я/думаю/где-то я читал, что .Net-среда поддерживает инъекции методов в классы - таким образом, все беспорядок вокруг IL потенциально позаботится.
Довольно точно, что методы инъекций, о которых вы говорите, будут использовать частичные классы. Я считаю, что принцип состоит в том, что два класса в одном и том же пространстве имен имеют одно и то же имя, а один - как частичный. Создана одна dll, включающая методы и свойства обоих классов. – Robert