2015-06-03 4 views
-1

У нас есть ситуация, когда на сервере с 8 ядрами инициализируется сервис за 6 минут, а для второго сервера с 32 процессорными ядрами требуется 35 минут для инициализации службы. После правильного профилирования мы увидели, что это связано с двумя API-интерфейсами ядра (get_counters и snmp_fold_field), которые пытаются собирать данные из всех существующих ядер и по мере увеличения количества процессорных ядер время выполнения занимает больше времени, чем ожидалось. Чтобы уменьшить инициализацию время, которое, как мы думали, отключили дополнительные ядра, а затем и инициализацию, включили все ядра процессора. Но в этом подходе мы также включаем синхронизацию всех ядер на вновь активированных ядрах, поскольку это ядро ​​SMP.Как удалить накладные расходы, вызванные увеличением количества ядер процессора

Может ли кто-нибудь предложить нам, как эффективно сократить накладные расходы, вызванные повышенным ядром процессора?


Вместо код я предпочел бы объяснить функции инициализации этой определенного пользователя системы service.During инициализации этот сервис прокладывает виртуальные интерфейсы на настроенных IP-адресах. Чтобы избежать дублирования ситуации с IP-адресами для каждого настроенного IP-адреса, он создает внутренний IP-адрес, и вся связь выполняется на интерфейсах, наложенных на внутренний IP-адрес. По мере того, как пакет достигает системы с назначением в качестве настроенного IP, правила таблицы Mangling/NATting/Routing применяются к системы для его решения. Интерфейс также позволяет настроить Ip, чтобы избежать переадресации IP-адресов. Наша проблема заключается в том, что мы масштабируем нашу систему, настроенную на 1024 IP-адреса на 8-ядерном компьютере, это занимает 8 минут, а на 32 ядра - 35 минут.

Дополнительная отладка, выполненная с использованием системного профилирования Мы видели, что модуль ядра ARPtables/IPtables потребляет больше всего времени в «get_counters()», а модуль ядра IP потребляет время в snmp_fold_field(). Если я просто отключу правила ARPtables Mangling, время сократится до 18 минут с 35 минут. Я могу поделиться коллажами модулей ядра, собранными с использованием профилировщика.

+0

Запишите небольшую программу, которая показывает поведение. –

ответ

0

Общим узким местом в приложениях с использованием многоядерных процессоров является неконтролируемый/-оптимизированный доступ к общим ресурсам. Самый большой убийца производительности - это блокировка шины (критические разделы), за которыми следуют обращения к ОЗУ, доступ к кешу L3 и доступ к кэшу L2. Пока ядро ​​работает внутри своих кешей L1 (код и данные), единственные узкие места будут связаны с плохо написанным кодом и плохо организованными данными. Когда два ядра должны выйти за пределы своих кэшей L1, они могут столкнуться при доступе к их (совместно используемому) кэшу L2. Кто будет первым? Являются ли данные даже там или мы должны переместиться в L3 или RAM для доступа к нему? Для каждого последующего уровня, необходимого для поиска данных, которые вы смотрите на 3-4-кратный штраф.

Что касается вашего приложения, похоже, он работал достаточно хорошо, потому что восемь ядер могут в определенной степени сталкиваться при доступе к общим ресурсам. С тридцатью двумя ядрами проблема становится более чем в четыре раза большей, потому что у вас будет четыре раза больше нагрузки на ресурс и в четыре раза больше ядер, чтобы решить, кому сначала нужно получить доступ. Это похоже на дверной проем: до тех пор, пока несколько человек забегают или выходят через дверной проем, сейчас нет проблем. Кто-то, приближающийся к дверному проему, может немного остановить другого. Внезапно у вас есть ситуация, когда многие люди работают и выходят, и у вас будет не только перегруженность, но и пробка.

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

Если это так, и вы по-прежнему настаиваете на том, чтобы работать быстрее на 32 ядрах, чем сегодня, вы смотрите на огромную работу, делая код SNMP-сервера более эффективным и организуя свои данные, чтобы уменьшить нагрузка на общие ресурсы. Не для слабонервных. Вы можете в конечном итоге переписать все приложение.

+0

Наше приложение использует очень меньшее количество потоков, но мы используем сторонние приложения, такие как «ip», «iptables» и «arptables», которые внутренне вызывают два apis get_sockopt() и recvmsg(). Эти API занимают больше времени в ядре. Соответствующие API в ядре для них - get_sockopt() и snmp_fold_field() [я упоминал их ранее]. –

+0

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

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