2009-09-28 2 views
14

Недавно я провел некоторое тестирование производительности и анализа приложения ASP.NET с использованием состояния сеанса вне процесса - это необходимо при использовании состояния сеанса в веб-ферме, чтобы состояние можно было восстановить на любой из веб-серверов, например если последующие HTTP-запросы поступают на другой сервер, потому что сеансы не «липкие» или исходный сервер не работает и т. д.Возможные решения для плохой производительности сериализации

Что меня удивило, когда я запускал веб-серверы при полной загрузке и профилировал использование ЦП что-то вроде 99% процессорного времени было потрачено на сериализацию и десериализацию состояния сеанса. Впоследствии мы реализовали настраиваемый государственный сервер «кэширования»; это всегда сериализует состояние, но также сохраняет состояние в памяти, так что, если вы используете липкие сеансы, состояние не нужно десериализовать большую часть времени. Это улучшило пропускную способность сервера в 2 раза; Однако сериализация по-прежнему составляет 98% или более времени процессора.

Мы получили некоторые дополнительные улучшения скорости путем «обрезки» ненужных ссылок на объекты между объектами в состоянии сеанса перед сериализацией - исправление ссылок вручную при десриализации. Это улучшило скорость еще на 10-20% или около того. Примером здесь является то, что некоторые потери производительности связаны с тем, что встроенная сериализация должна идти по графику указателей объектов, что становится более сложной задачей с большим количеством указателей.

Продолжая исследование, мы написали индивидуальные процедуры сериализации для некоторых наших классов, а не полагаемся на встроенную сериализацию .Net. Мы обнаружили, что производительность была значительно улучшена, примерно в 50x. Похоже, что основная часть загрузки ЦП обусловлена ​​встроенной сериализацией .Net, которая, в свою очередь, медленна из-за использования использования Reflection для перемещения указателей/графиков объектов и извлечения данных поля.

Это очень заманчиво увеличить нашу производительность на 50 раз, таким образом уменьшая требования к аппаратным средствам веб-сервера с большим коэффициентом (и потребностями в энергии меньшим, но все же значительным фактором). Возможные варианты:

1) Напишите индивидуальную сериализацию. Это проблема из-за сложности задачи и затрат на обслуживание, которые она генерирует, то есть любые изменения состояния класса требуют изменения в процедурах сериализации/десериализации.

2) Некоторые сторонние решения. Возможно, какой-то продукт, который автоматически генерирует код сохранения состояния/загрузки во время сборки, тем самым устраняя необходимость использования Reflection.

Мне было бы очень интересно узнать, знает ли кто-нибудь о стороннем решении, или столкнулся с этой проблемой, поскольку я не нашел упоминания об этом из интернет-поиска.

ОБНОВЛЕНИЕ: Некоторые из них предложили своего рода решение на полпути между встроенной сериализацией по умолчанию и чистыми настраиваемыми процедурами сериализации. Идея заключается в том, что вы реализуете персонализированную сериализацию для классов, которые влияют на производительность больше всего, например. преодолевая ISerializable. Это интересный и многообещающий подход; Однако я по-прежнему считаю, что есть возможности для полной замены встроенной сериализации без необходимости писать и поддерживать какой-либо пользовательский код - это невозможно сделать во время выполнения, потому что Reflection необходим для запроса объектов и доступа к личным данным. Но теоретически возможно послепродавать уже построенные сборки и внедрять новые методы в качестве дополнительного шага сборки. Некоторые профилировщики используют этот подход для ввода кода профилирования в сборки после того, как они были созданы компилятором C#. Также я/думаю/где-то я читал, что .Net-среда поддерживает инъекции методов в классы - таким образом, все беспорядок вокруг IL потенциально позаботится.

+0

Довольно точно, что методы инъекций, о которых вы говорите, будут использовать частичные классы. Я считаю, что принцип состоит в том, что два класса в одном и том же пространстве имен имеют одно и то же имя, а один - как частичный. Создана одна dll, включающая методы и свойства обоих классов. – Robert

ответ

2

К сожалению, я знаю только вариант 1 и tbh, который может стать очень болезненным для работы.

Но он делает только то, что вы хотите, так что он так же быстро, как и получается.

Удачи.

+0

Я принимаю это как ответ, потому что мы обнаружили, что все другие решения по меньшей мере на 10 раз медленнее, чем написание настроенного кода. – redcalx

1

Еще один вариант - отключить ViewState для всех элементов управления, которые не затрагиваются на обратной стороне сервера.

+0

Значительная часть государства принадлежит к нашим собственным классам, но да, из состояния стандартных элементов управления ASP.NET должно быть состояние, так что определенно стоит следить за ними. Благодарю. – redcalx

1

Вы можете частично настроить сериализацию, реализовав ISerializable. Если вы сделаете это для худших нарушителей, вы не будете увеличивать обслуживание, но все равно получите некоторое ускорение.

+0

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

1

Существует стороннее решение: отличная библиотека с открытым исходным кодом

Саймоном Хьюитта см Optimizing Serialization in .NET - part 2.

Я using it in my application и получил аналогичное ускорение , как вы, 20-40 раз.

Он устраняет отражение, которое является причиной замедления , но для списков он поддерживает только несколько нативных типов. Так что для Genreric.List ваших собственных типов должен быть явный код где-то или другой. Например. явные петли или что-то умнее, что автоматизирует это. В любом случае это довольно просто и не должно быть препятствием для огромных преимуществ .

+0

Спасибо, много интересной информации здесь. На первый взгляд кажется, что он расположен на полпути между использованием встроенной (медленной) и чистой персонализированной сериализации. Он поросенок поддерживает встроенную сериализацию, которая также была предложена одним из других ответов. – redcalx

0

Мы столкнулись с подобными проблемами и разработали несколько способов повышения производительности. Мы используем некоторые из них в нашем картографическом продукте памяти Persistore (в настоящее время бета). В нашем случае мы можем просто получить доступ к сохраненным данным «in situ», потому что он всегда находится в кучке памяти.

Однако один «трюк», чтобы определить ваши данные о состоянии сеанса (если это возможно), как marshalable класса/структуры и «сериализации», что с помощью поддержки .NET сортировочной, это может быть очень быстро на самом деле, но не будет обрабатывать Графы «объект».

Мы также поддерживаем специальное сохранение на основе двоичной сериализации, но мы также извлекаем и сохраняем метаданные, чтобы управляемый код мог устанавливать/получать поля в памяти, сохраняемой в процессе выполнения, без необходимости десериализации всего объекта, это полезно в некоторых настройках (например, ценные бумаги и обновления цен на акции и т. д.). Наша последняя бета-версия поддерживает сериализацию по сети, LINQ анонимных типов, это первый, насколько мне известно.

В любом случае нам было бы интересно иметь новых бета-клиентов, которые подталкивают проблемы ASP.NET и веб-производительности, наша последняя бета-версия очень впечатляет (но не готова до недели nex).

Если кому интересно, просто свяжитесь с нами для получения последней информации о продукте.

Хью Моран

PS: Сайт устарел, продукт выходит далеко за пределы того, что описано здесь.

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

  • Нет связанных вопросов^_^