Затраты .NET IOCP ThreadPool с асинхронными операциями UDP - PullRequest
3 голосов
/ 26 мая 2011

Я разработал медиасервер VoIP, который обменивается RTP-пакетами с удаленными конечными точками SIP.Он должен хорошо масштабироваться - и хотя я изначально был обеспокоен тем, что моя реализация C # не будет приближаться к версии C ++, которую он заменяет, я использовал различные профилировщики, чтобы отточить реализацию, и производительность довольно близка.

У меня естьустранение большинства распределений объектов путем создания пулов многократно используемых объектов, я использую ReceiveFromAsync и SendToAsync для отправки / получения дейтаграмм и использую очереди производителя / потребителя для передачи пакетов RTP по системе.На машине с 2 процессорами Xeon 2,4 ГГц теперь я могу обрабатывать около 1000 одновременных потоков, каждый из которых отправляет / получает 50 пакетов в секунду.Однако итеративный профиль / tweak / profile меня зацепил - и я уверен, что где-то там больше эффективности!

Событием, запускающим обработку, является делегат Completed, вызываемый на SocketAsyncEventArgs - который, в свою очередь, отправляетпакеты RTP через конвейер обработки.

Остается разочарование тем, что в пуле потоков IOCP, по-видимому, имеются значительные издержки.Профилировщик показывает, что только 72% времени Inclusive Sample занято в «моем коде» - время, предшествующее этому, кажется накладным на пул потоков (кадры стека ниже).

Итак, мои вопросы:

  1. Я что-то упустил в моем понимании?
  2. Можно ли уменьшить эти издержки?
  3. Можно ли заменить пул потоков, используемый асинхронными функциями сокетов, на использование пользовательских,легкий пул потоков с меньшими накладными расходами?
100% MediaGateway

95.35% Thread::intermediateThreadProc(void *)

88.37% ThreadNative::SetDomainLocalStore(class Object *)

88.37% BindIoCompletionCallbackStub(unsigned long,unsigned long,struct _OVERLAPPED *)

86.05% BindIoCompletionCallbackStubEx(unsigned long,unsigned long,struct _OVERLAPPED *,int)

86.05% ManagedThreadBase::ThreadPool(struct ADID,void (*)(void *),void *)

86.05% CrstBase::Enter(void)

86.05% AppDomainStack::PushDomain(struct ADID)

86.05% Thread::ShouldChangeAbortToUnload(class Frame *,class Frame *)

86.05% AppDomainStack::ClearDomainStack(void)

83.72% ThreadPoolNative::CorWaitHandleCleanupNative(void *)

83.72% __CT??_R0PAVEEArgumentException@@@84

83.72% DispatchCallDebuggerWrapper(unsigned long *,unsigned long,unsigned long *,unsigned 
__int64,void *,unsigned __int64,unsigned int,unsigned char *,class ContextTransitionFrame *)

83.72% DispatchCallBody(unsigned long *,unsigned long,unsigned long *,unsigned __int64,void *,unsigned __int64,unsigned int,unsigned char *)

83.72% MethodDesc::EnsureActive(void)

81.40% _CallDescrWorker@20

81.40% System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint32,uint32,valuetype System.Threading.NativeOverlapped*)

76.74% System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(uint32,uint32,valuetype System.Threading.NativeOverlapped*)

76.74% System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(valuetype System.Net.Sockets.SocketError,int32,valuetype System.Net.Sockets.SocketFlags)

74.42% System.Threading.ExecutionContext.Run(class System.Threading.ExecutionContext,class System.Threading.ContextCallback,object)

72.09% System.Net.Sockets.SocketAsyncEventArgs.ExecutionCallback(object)

72.09% System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(class System.Net.Sockets.SocketAsyncEventArgs)

Ответы [ 2 ]

1 голос
/ 13 июня 2011

50000 пакетов в секунду в Windows - это неплохо, я бы сказал, что аппаратное обеспечение и операционная система - более важные проблемы для масштабирования. Разные сетевые интерфейсы накладывают разные ограничения: сетевые адаптеры Intel имеют преимущественно высокую производительность с хорошими кроссплатформенными драйверами, однако Broadcom не имеют хороших результатов в Windows по сравнению с Linux. Расширенные API-интерфейсы ядра сети Windows доступны только в том случае, если драйверы поддерживают эти функции, и Broadcom доказала, что является компанией, которая включает расширенные функции только для более нового оборудования, несмотря на поддержку более старых устройств из других операционных систем.

Я бы начал исследовать несколько сетевых адаптеров, например, с четырехядерным серверным сетевым адаптером и использовать расширенные сетевые API-интерфейсы Windows для привязки одного сетевого адаптера к каждому ядру обработки. Теоретически вы можете отправить 50 000 через один сетевой адаптер и 50 000 через другой.

http://msdn.microsoft.com/en-us/library/ff568337(v=VS.85).aspx

Однако, похоже, у вас нет базовых показателей для оценки эффективности кода. Я ожидаю увидеть сравнение с серверами, не использующими полезную нагрузку VoIP, работающими на транспорте TCP вместо UDP и работающими в других операционных системах для сравнения стека IP и эффективности API.

0 голосов
/ 27 сентября 2011

Просто добавьте немного информации - я недавно обнаружил, что в пуле потоков IOCP присутствует ошибка, которая может повлиять на вашу производительность: см. Пункт 3 раздела «причина» в http://support.microsoft.com/kb/2538826. Это может быть допустимо для вашегослучай.

...