-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
alexk99 patches #9
base: master
Are you sure you want to change the base?
Conversation
const u32 tok = delta_ms * (car->cir / (BITS_PER_BYTE * MSEC_PER_SEC)); Раccчет tok не зависит от переменных, изменяемых внутри критической секции (cs). Он зависит от delte_ms, которая рассчитывается вне cs и от cir - фактически константа. Если в рассчет tok подставить формул delta_ms, пыполнить сокращения, то останется (now - car->last) * (car->cir / (HZ * BITS_PER_BYTE)) Можно выссчитывать вот эту часть заранее, избавившись от лишнего деления (он ведь дорогие, вроде дороже умножения). car->cir_hz = (car->cir / (HZ * BITS_PER_BYTE)) В итоге получим const u32 tok = (now - car->last) * car->cir_hz; Конечно, добавится умножение в выводе статистике, она же должна много реже выводиться. 2) критическую секцию можно еще упростить, вынести статистику во вне и переведя ее на atomic операции. Правда в случае включенного RATE_ESTIMATOR укоратить cs вроде не получается, но вот я бы у себя его выключил. Это ведь тоже только статистика, правильно? 3) переменная struct ratelimit_stat.first нигде не используется. просто удалил.
Спасибо! Выгладит всё корректно. Небольшие комментарии:
Не красиво выглядят "игры" с
Надеюсь вы понимаете, что выигрыш по скорости на современных процах будет минимальный. |
Можно оставить старое, не принципиально. |
cir_hz is renamed back to cir
…ection is entered only when bucket is full.
код стал попроще и я разглядел в нем еще идею для проверки. первые тесты вроде проходят. сейчас сделаю набор тестов c iperf'ом, чтобы поточнее. Сразу понимаю вопрос а нафига? никто, вроде, и так не замечает влияние модуля в линуксе. Мне хочется получить реально быструю процедуру прохождения пакетами ведра, чтобы многопоточный код, в моем случае dpdk, где pps будет высоким и воркеры будут сильно конкурировать за доступ к ведру, не стал узким местом. |
У вас патчи меняющие смысл кода. Например, не будет ли вредной race condition в последнем случае (e2f5d7f)? Вероятно, надо обосновать в комментах или дескрипшене патча почему это не критично. Иначе, код выглядит на первый взгляд как ошибочный и через время у людей может возникать желание его исправлять. А на второй взгляд, (Да и код с локом нельзя назвать lockless.) |
race какой переменной?
Она читается до лока в оригинальном коде.
Да, тут у меня ошибка в случае racе переменной tc. Точно, могут отброситься оба пакета, хотя один из них еще мог бы пройти.
В общем случае да. Но если большинству транзакций не нужны локи, то эти случаи и будут lockless. Идея в том, в этом алгоритме можно попробовать не на каждый пакет делать пополнения ведра, в dpdk библиотеке предлагают делать это по истечении заданного время, например. Вторая идея в том, что большая часть пакетов не должна отбрасываться как только скорость стабилизировалась, Я еще подумаю на вторым патчем. Для этого и сделал пометку, debug. Идея была начать обсуждение. А первый патч не меняет логику совсем. Еще раз его проглядел, результат должен быть один в один с оригинальным кодом. |
Если не на каждом делать пополнение ведерка или наоборот 1 пакет может влиять на другие (из-за race condition), то это уже другой алгоритм. А люди ожидают от ipt-ratelimit алгоритм Cisco RED-like. Первый патч меняет логику, но не ухудшает, так что ок. |
Я абсолютно согласен, что алгоритм не должен меняться. Для второго патча
еще есть идеи.
А в чем изменение логики работы алгоритма у первого патча?
23 декабря 2016 г., 16:10 пользователь ABC <[email protected]>
написал:
… Если не на каждом делать пополнение ведерка или наоборот 1 пакет может
влиять на другие (из-за race condition), то это уже другой алгоритм. А люди
ожидают от ipt-ratelimit алгоритм Cisco RED-like.
Первый патч меняет логику, но не ухудшает, так что ок.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#9 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/APS272IwwNqmBTw35nUO93QyYtr0upBsks5rK8hKgaJpZM4LUO6I>
.
--
--
Kiselev Alexander
|
Вода вытекала каждую миллисекунду, а стала каждый jiffy. Это могло повлиять на вид пропускаемого трафика. |
(Только сейчас заметил этот комментарий.) Да, надо проанализировать это. |
Баг. Токены могут вытекать быстрее чем нужно. |
Про мсек и токены. Это некорректное утвержение.
Давайте смотреть.
было
const unsigned long delta_ms = (now - car->last) * (MSEC_PER_SEC / HZ);
if (delta_ms) {
const u32 tok = delta_ms * (car->cir / (BITS_PER_BYTE * MSEC_PER_SEC));
car->tc -= min(tok, car->tc);
стало
const u32 tok = (now - car->last) * car->cir;
if (tok) {
car->tc -= min(tok, car->tc);
1) конечный рассчет значения tok в обоих случаях идентичный,
в это можно убедиться, просто развернув вычисления:
было
tok = delta_ms * (car->cir / (BITS_PER_BYTE * MSEC_PER_SEC)) =
(now - car->last) * (MSEC_PER_SEC / HZ) * (car->cir / (BITS_PER_BYTE *
MSEC_PER_SEC)) =
(now - car->last) * cir / HZ / BITS_PER_BYTE;
стало
const u32 tok = (now - car->last) * car->cir = (now - car->last) * val /
(HZ * BITS_PER_BYTE) =
= (now - car->last) * val / HZ / BITS_PER_BYTE;
здесь надо учесть, что val и это есть сir из первого кода
т.е. рассчета tok совершенно идентичный
2)
Если следовать утверждению, что второй вариант меняет алогоритм, то
остается проанализировать условия if (delta_ms) и if (tok).
т.е. чтобы алгоритм был разным, надо чтобы были случи когда в первом
варианте условие выполняется,
а во втором варианте кода - нет. Я таких случаев не вижу. В формулах второй
множитель в обоих случаях
всегда ненулевой, а первой в обоих формулах идентичный.
Поэтому вода и токены здесь суть одно и тоже, в итогде вычитаются токены. И
срабатывают эти вычитания
совершенно идентично.
Что я упустил?
P.S.
Бага, из последнего замечения про быстрее утекает, это возможно это не
отменяет. Но тут я подумаю.
2016-12-23 16:48 GMT+03:00 ABC <[email protected]>:
… Да, надо проанализировать это.
Баг. Токены могут вытекать быстрее чем нужно.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#9 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/APS274-8HAZwdhqziYrb_fHHmHSoPwoAks5rK9EggaJpZM4LUO6I>
.
--
--
Kiselev Alexander
|
ошибся, воду читать как мсек. но суть таже |
я тоже к чужому коду отношусь порой критичнее, чем к своему. Т.е. так как чтение last показалось в моем коде, то сразу нашелся повод подумать сильнее. Ну это нормально )) |
да, last чтение должно быть внутри cs, иначе поток прочитает его, зависнет в входе в cs, другой |
Я предполагаю, что не меняя конечного результата, т.е. для каждого пакета итоговое решение не должно поменяться по сравнению с оригинальным алогоритмом, можно изменить сам алгоритм обработки пакетов, так чтобы большинство из них обрабатывались быстрее, проходя простой и короткий путь без взаимных блокировок. Допустим, пришло пять пакетов. Не важно один и несколько потоков. Оригинальный алогоритм для каждого пакета пытается выполнить два шага (пока не берем в рассчет переполнение корзины): 1) добавить рамер пакета в корзину; 2) если накопились токены (прошло время) вычесть из корзины накопленные токены; Допустим в корзине достаточно токенов для обработки первых 4 пакетов. Тогда для каждого пакета будет выполняться только вычетание. Пакеты чаще идут быстро друг за другом, поэтому пополнений корзины не будет. Переполнений пока тоже нет. Для для таких случаев можно написать алгоритм только с вычитанием, назвав его условно fast path. Отличия от предыдущего патча в том, что теперь я отслеживаю конфликты гонок с помощью СAS (compare and swap), гарантированно соблюдая условие достаточности токенов для каждого отдельного пакета. На этом этапе можно не думать о пополнениях корзины, даже если и пора. Это можно сделать позже, накопления не пропадут, т.к. время last пока не меняется. Пробуя пройти fast path для 5ого последний пакета, замечаем, что в корзине переполнение и идем по медленному пути с критической секцией. Здесь все внутри секции, никаких сюрпризов. И последний шаг. Fast path могут пересекаться с другими fast path, они thread safe за счет CAS. Но, fast path одного потока не должен пересекаться с CS slow path другого. Для этого добавляем exlusive/shared (или read/write) блокировку вместо spinlock'а. Shared блокировки дешевые, не должны влиять на производительно быстрых секций. Правда exlusive дороже, чем обычная. Предполагаем, что в итоге суммарная польза от одновременной работы быстрых, путей превысет намного потерю от более дорогих, но редких exclusive (write) блокировок. P.S. Снова пока не думал про estimator.
Сделать полностью lockless (или waitless) интересная задача, надо подумать... |
полностью lockless не выйдет, т.к. в случае переполнения корзины никуда не деться, надо добавлять в корзину накопившиеся токены и одновременно обновлять last time. Для двух операций, нужен dcas. Если я ничего не упустил в своем последнем патче, должно быть уже хорошо. Думаю о том, как сделать тесты. Т.к. на живой сети совершенно не понятно сколько там параллельных воркеров linux запускает для двух iperf'ов на два разные dst ip. Хочу сделать синтетический, с 6 настоящими тредами. |
Сделал тесты реализации последнего патча, назовем ее fast/slow (FS) версией. Делал два теста: один на корректносить, второй на производительность. Тест на корректность проверял, что решения для тестового набора пакетов принимаются С производительностью все совсем не очевидно. Вывод, Это тест для 4 ядер, интересно, что будет с ростом числа ядер. процента red от общего числа пакетов -- profit Есть разброс в результатах, по-хорошему, его бы автоматизировать, сделать сотни прогонов и построить нормальную табличку. Если интересны все эти размышления, то поделитесь пожалуйста статистикой, какие у реальных пользователей green/red счетчики. |
Да, линуксе rwlocks очень медленные поэтому их не рекомендуют использовать. (Навскидку нагуглилось https://lwn.net/Articles/364583/) Про DPDK не знаю. Поэтому никакой реализацией с rwlocks не ускорить то что уже есть. |
в хороших реализациях r-блокировки реализованы как lockless в отсутствии w блокировок. в dpdk, похоже, с ними все хорошо. но 20 процентов в лучших случаях - конечно маловато. я надеялся будет лучше. но все равно интересный опыт. заодно баг нашли в вашей реализации. так что насчет статистики? не сложно сделать выборку по десятку другому пользователей на предмет red счетчиков? Попутно, а в чем смысл дополнительной логики с extended сir по сравнению с классическим tbf? пользователь может понять разницу? можно просто линк на какую-нибудь публикацию, если такие есть. Спасибо. |
Мне не отчитываются по статистике. Но могу глянуть по одному юзеру позже. extended сir это RED-like фишка циски.
Вам её не обязательно реализовывать, есть еще стандартные алгоритмы (RFC2697, RFC2698). https://www.freebsd.org/cgi/man.cgi?query=ng_car&apropos=0&sektion=4&manpath=FreeBSD+11-current&arch=default&format=html (Я смотрю там появился "Traffic shaping with RED", раньше этого не было.) |
да, ок. спасибо. за ссылки
|
под пользователями я имел ввиду не пользователей модуля, а пользователей-абонентов сети,
они сложнее, цисковский как раз золотая середина. ответ на свой вопрос я нашел в описании red, вроде не новый алгоритм, но только вот сейчас прочитал про реальные ситуации, где он помогает: https://en.wikipedia.org/wiki/TCP_global_synchronization |
Статистика у пользователей модуля, а не пользователей сети. Или я не понял что вам нужно. |
именно ее, red и green счетчики пакетов. я имел ввиду, что было бы
достаточно десяток-два таких счетчиков или их можно разом все вывести одной
командой?
26 декабря 2016 г., 1:02 пользователь ABC <[email protected]>
написал:
… под пользователями я имел ввиду не пользователей модуля, а
пользователей-абонентов сети,
предполагая, что у вас есть доступ к своей сети.
Статистика у пользователей модуля, а не пользователей сети. Или я не понял
что вам нужно.
—
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHub
<#9 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/APS279C_74OXqqWAzygmBoWezK2L9E5Mks5rLufkgaJpZM4LUO6I>
.
--
--
Kiselev Alexander
|
надо написать код, чтобы дальше говорить, а то запутаемся. я все время путаю, что в текущем коде обратная логика, refill корзины - это вычитание, pkt_len - это добавление. В пред. комментарии у меня наоборот. |
Второй cas нужен так как от tc надо отнимать до 0, но не больше (наполнять ведерко до максимума, но не больше). Поэтому просто atomic вычитание сделать нельзя. |
ну да, без кода перед глазами я забыл про это, да нужен. cas. Получается 3 cas подряд. Надо подумать, каждое ли из этих 3 состояний корректно, так лучше всего размышлять о таких алгоритмах, как o state machine с переходами. |
кстати, вспомнил, что я в самом начале размышлений о tbf искал lock-less реализации и нашел одну. она мне тогда показалось неправильной, плюс на go. решил забить, но теперь мне кажется по-другому. возможно, будет интересно взглянуь https://github.com/tsenart/tb |
К сожалению, выяснилось, что у него больше нет нужной информации. |
ок, спасибо. не беда, может кто на наге поделится. |
u32 tok;
spin_lock(&ent->lock_bh);
tok = (now - car->last) * car->cir;
car->tc += len; /* перенести ниже этого фрагмента */
if (tok) {
car->tc -= min(tok, car->tc);
car->last = now; /* апдейтить выше */
}
/* код выше переделать на CAS */
/* spin_lock(&ent->lock_bh) передвинуть сюда */
/* car->tc += len; передвинуть сюда */ Можно и не весь алгоритм сразу заменять на cas, а скажем начать только с апдейта Во время worst case сочетаются одновременно три условия: а) пакеты нужного трафика есть на всех тредах, (скажем их 8), б) бочёнок полностью заполнен, в) подошло время добавления токенов. Следствия: 1) Никто не гарантировал, что это время настанет именно сейчас, а не на миллисекунду позже - значит все 8 пакетов могли спокойно дропнуться сейчас. 2) "Справедливо" обработается пакет в треде, который вычисляет токены, а остальные 7 могут успеть дропнутся пока идут вычисления между подсчетом времени и токенов. Контраргумент к последнему - всё равно правильно вычислится кол-во места в бочёнке, только лишь с задержкой на время обработки оного пакета (в который может попасть 8 пакетов из-за паралеллизма), а так как эта задержка случайна (см п.1), то она и не важна. 3) Чем чаще будет апдейтиться
Речь не об ошибках, а о вероятностности. RED и не будет получен, но влияние того, что пакет дропается "не в том" треде влияет не больше чем эффект RED(-like). Нет большого смысла сохранять строгую последовательность выполнения cs, так как пакеты и так распределяются между тредами вероятностно, плюс, RED-like алгоритм их всё равно дропает не упорядочено. |
да, я понимаю о чем вы, последовательность событий в этом алгоритме совершенно не важна. только запостил еще версию, вроде работает. весь алогитм получилось уместить в два casа. ключевой момент - с помощью 64 битного cas можно получить dcas и атомарно обновлять два 32 битных значения сразу. |
Я изменял свой пост по ходу написания много раз. Сейчас последняя версия. ;-) |
Посмотрел, пока странно почему у вас |
atomic_t - это синтаксический сахар, внутри там long. лень было исправлять, переделывать инициализатор #ifdef CONFIG_64BIT |
сейчас поправлю, будет смотреться правильнее, конечно |
Я имел ввиду, конечно, не только тип, а почему со значением работа не как с |
да, да.. правлю.. но на x86 чтения из памяти всегда атомарные, я это имел ввиду, когда сказал, что было лень. я знал, что будет работать. но правильно конечно делать load |
поправил все атомики и небольшой баг. Собираюсь perfomance тесты сегодня сделать. |
Почти ровно в раза быстрее lock-less версия получилась. Теперь можно в страивать в the_router :) |
Поздравляю! А (многие) люди ещё хотят полисинг не per IP, а per subnet. Я начинал делать, но забросил из-за недостатка времени. Очередное поле для замедления вычислений. |
Я сейчас думаю о минимально базовых вещах, необходимых для ipoe bras. Поэтому пока всякие редкие фичи вне поля интересов. Да, со временем у всех беда. Без особой надежды, конечно, спрашиваю, но может вам интересно будет поучаствовать в разработке софтового браса на dpdk? Я хочу сделать коммечерский продукт. Сейчас половину своего времени трачу на него. И хочется двигаться быстрее. Временное окно небольшое, год, другой и кто-нибудь займет место на рынке. |
Заняться full-time или в свободное время? |
Бюджета освоить у меня, к сожалению, нет. Поэтому фулл тайм, только если сами захотите, если вдруг как у меня есть источники дохода, не требующие постоянного внимания. |
Т.е. другими словами я партнеров ищу. Вложить время и умения сейчас с надеждой, что взлетит ) |
Понятно, но нет пока свободного времени с моей нынешней работой (последний год), в этом и проблема пока не решенная. |
a8d91df
to
640851a
Compare
const u32 tok = delta_ms * (car->cir / (BITS_PER_BYTE * MSEC_PER_SEC));
Раccчет tok не зависит от переменных, изменяемых внутри критической секции (cs).
Он зависит от delte_ms, которая рассчитывается вне cs и от cir - фактически константа.
Если в рассчет tok подставить формул delta_ms, пыполнить сокращения, то останется
(now - car->last) * (car->cir / (HZ * BITS_PER_BYTE))
Можно выссчитывать вот эту часть заранее, избавившись от лишнего деления (он ведь дорогие,
вроде дороже умножения).
car->cir_hz = (car->cir / (HZ * BITS_PER_BYTE))
В итоге получим
const u32 tok = (now - car->last) * car->cir_hz;
Конечно, добавится умножение в выводе статистике, она же должна много реже выводиться.
критическую секцию можно еще упростить, вынести статистику во вне и переведя ее на atomic операции.
Правда в случае включенного RATE_ESTIMATOR укоратить cs вроде не получается, но вот я бы у себя
его выключил. Это ведь тоже только статистика, правильно?
переменная struct ratelimit_stat.first нигде не используется.
просто удалил.