Обновить
70
Антон Кортунов@ToSHiC

Программист

25
Подписчики
Отправить сообщение
Пока читал введение — не покидало ощущение, что вы — СЕОшник, а текст лежит на сайте магазина обуви и пытается продать мне сапоги.
Всё, я понял ваше недопонимание. В современных операционных системах, работающих на многоядерных процессорах, когда вы создаёте mutex на самом деле создаётся futex. Различие в том, что он сначала делает spin wait некоторое время (достаточное, чтобы несколько раз обратиться к памяти мимо всех кэшей), то есть ведёт себя как спинлок, а если после этого лок всё ещё не взят, то делается уже классический ядерный мьютекс и поток засыпает. В линуксе это точно так, вот страничка из мана: linux.die.net/man/2/futex.

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

Проблема не в блокировках consumer на извлечении элементов из очереди, тут то как раз всё хорошо обычно. Проблема в том, что при 160 активных тредах на 16 физических ядер шансы того, что consumer тред активен одновременно с нашим, запихивающим данные, 10%. А когда consumer отработает, в следующий квант, то наш уже будет вытеснен. Производительность, если не использовать спин-вейты, не упадёт, а вот latency вырастет. Можно повысить приоритет consumer треда, и это даже может помочь. А может всё, наоборот, станет медленнее. И прирост от нагрузки может сильно зависеть.

Я совершенно согласен с вами, что если работа по обработке достаточно большая по времени, то очереди становятся неплохой идеей. Что такое «достаточно большая» — вопрос, который надо исследовать на реальной системе с реальной нагрузкой. В таком исследовании я бы отталкивался от цифры в 10 квантов.
latency(положить в очередь) + latency(обработать) + latency(получить результат)
будет больше, чем
latency(взять лок) + latency(обработать) + latency(отпустить лок)
из-за решедулингов. А они, в свою очередь, зависят от количества ядер и количества активных потоков.

Дисковое IO в линуксе на самом деле всегда синхронное, просто при использовании aio_* блокироваться будет не ваш поток, а специально созданный ядерный поток. Я упомянул IO в контексте того, что потоков на порядок, а то и на несколько порядков больше, чем ядер процессора. Начал какой нибудь logrotate или syslogd синкать данные на диске, скушал много процессора — и очередь резко стала работать медленней.
Вы рассматриваете варинат std::queue + condition variable вместо специализированой очереди?

Какая бы очередь не была, нам всё равно надо каким-то образом получить результат, правда? Это может быть не кондишн, а while(cond) со слипом внутри, не суть важно. Главное, что мы ждём. Вы можете возразить, что мы можем вместо ожидания вернуть в ивентлуп и продолжать делать полезную работу, но это уже совсем другая песня.

При высокой загрузке в очереди постоянно будут элементы, поэтому consumer не будет ждать, он будет просто каждый раз извлекать новый элемент без ожидания. К тому же, ждать элементов в очереди можно с помощью busy wait, если так важна латентность.

Это если потоков столько же, сколько ядер. В реальности, если вы работаете с данными на диске, то потоков будет сильно больше, и consumer будет регулярно вытесняться. Я всё к тому, что реальная latency очереди может оказаться больше, чем кажется на первый взгляд, и про неё уже нельзя забывать, если время ответа всего сервиса измеряется в десятках миллисекунд.
Если один поток ждет данные а другой — предоставляет, то, если оба потока выполняются, никакого переключения контекста не будет, мьютекс там, либо атомарная переменная.
Если поток пытается захватить мьютекс, а он уже захвачен, то это приведет к переключению контекста. В случае lock free очереди — переключения контекста не будет, поток потратит свой квант времени на busy wait на этой самой очереди. На практике, накладные расходы появляются тогда, когда очереди сильно выростают, начинают жрать память и приводить к кэш промахам.

Если есть только один мьютекс, и 2 потока работают с защищаемой им переменной, то переключение контекста будет в том случае, если оба потока одновременно выполняются (очевидно, многоядерная система должна быть) и лочат на чуть большее время, чем работает спинлок, либо если один залочил и его зарешедулила ОС. Если операция лёгкая, то чаще всего никого не зарешедулят и всё ограничится спинлоком. Если одновременно работает 1 поток — то всё вообще отлично.

Когда появляется очередь, приходится использовать кондишены. Если разгребающий поток не будет активным — то ожидающий наверняка будет зарешедулен. Если очередь более-менее длинная, то ожидающий опять же будет зарешедулен. То есть если у вас 200 потоков на 16 ядер, то с высокой вероятностью постановка задания в очередь и получение результата в одном кванте не выполнится. Если операция долгая, то ничего страшного. Если операция быстрая, типа Key value store — то очередь только замедлит всё.

Пишите, если я где-то не прав. Выше я что-то маху дал на счёт 40мс, при HZ=250 квант всё же 4мс.
Фраза «Чем отличаются поисковые подсказки Evernote от любых других?» звучит круто, но они не так уж сильно отличаются от подсказок в тех же почтовых сервисах.
Да, но с очередью вы сразу добавляете много накладных расходов. Если потоков больше, чем ядер (а это нормальная ситуация, если вы работаете с сетью) вы получаете +2 кванта времени (80мс на современных серверных ядрах линкса), которые ушли на решедулинг, хотя в случае мьютекса хватило бы одного спинлока и времени бы вообще не потеряли. 6 обращений к кэшу — и вы внезапно получили плюс пол секунды к времени работы функции.

Lock-less структуры данных это штуки, которые практически невозможно оттестировать и крайне сложно отловить в них баги. Избегайте их как только можете, потому что в реалиях многоядерных систем мьютекс, а точнее фьютекс, превращается в спинлок, который работает очень быстро в случае лёгкий операций типа «добавить собщение в очередь».
Как предлагаете делать очередь без локов? Только давайте практические реализации, проверенные, т.к. во многих учебных примерах, например, есть ABA проблема.
Антенны находятся в разных частях самолёта для улучшения качества приёма-передачи. Вдоль фюзеляжа проходит несколько километров проводов, по которым, в том числе, идут сигналы управления хвостовым оперением. Это 50 лет назад всё оборудование было размещено в кабине пилотов.
Для curl_multi_* нужен внешний ивентлуп, во всяком случае в сишной либе. В итоге код получается на порядок сложнее, чем при использовании curl_easy*.
Так выедаются сокеты, а не порты, это же разные вещи!

Кстати говоря, в случае Connection: close сокеты тоже выедаются, потому что они потом болтаются в TIME_WAIT 2msl (2 часа в случае линуксов). Чтобы с этим бороться в линуксе есть tcp_tw_recycle и tcp_tw_reuse.
Можно по-подробней, как keep-alive выжирает порты сервера?
Честно говоря, мне «Пример 3. Практически идеал: инкапсуляция локов» нравится больше, чем KeyValueStorage как с точки зрения кода, так и с точки зрения дальнейшего использования. Длинная стрелка, которая ещё иногда и короткой становится — совершенно неочевидная штука. Дополнительной проблемой может стать сокрытие локов от программиста, в результате можно получить разный порядок взятия локов (и это будет не сразу видно из-за врапперов), а это — прямой путь к дедлокам.
Похоже на красивую цифру 35 000 футов.
Есть один тонкий момент — гражданские GPS приёмники обычно предполагают, что вы находитесь на высоте меньше 10 000м, когда пытаются определить местоположение. Есть ещё ограничение по скорости в 1000км/ч, но гражданские самолёты (не Конкорд/Ту144) так быстро не летают. Если вдруг приёмник сможет найти своё положение, то, возможно, будет и на высоте больше 10000м показывать координаты, т.к. уже «зацепился». Ну и cold start занимает 13.5 минут при хорошей видимости спутников, так что ждать иногда надо долго.

Есть ещё локальные ограничения для производителей. ITAR ограничивает максимальную высоту в 60 000 футов и обещают делать атата всем производителям в США, кто нарушает эти правила без специального на то разрешения.
Горизонтальная и вертикальная скорости квадрокоптера зависят от углов тангажа и крена, как и у вертолёта. Нельзя рассматривать изменение скорости вращения винтов в отрыве от этих углов, ведь ровного полёта не существует, как минимум всегда есть ветер, искажения потоков воздуха всякими предметами, находящимися рядом, и неравномерности в оцифровке PWM сигнала, работе двигателей и винтов. Скорее всего, если пользоваться вашим вариантом, колбасить коптер будет не по детски. Ну и барометр нужен, чтоб вертикальную скорость знать.

Тяга даже SF винтов растёт почти линейно до скорости порядка 10 м/с. Если хочется лететь быстрее — то можно E винты поставить и разгоняться до 20 м/с. Это я к тому, что на низких скоростях полёта линейная тяга — хорошее приближение.
Шантаж кого кем? Если частных лиц частными, то проще подкупить админа местного провайдера, чем сотрудника АНБ. Да и всякие частные детективы есть. Для влияния же на массы надо им что-то транслировать, тут СМИ намного лучше подходят.
А по вашему нечего? В данном случае вина за сбой на баге во внешней библиотеке. Или в вашей картине мира виной чего-либо может быть только человек?

И что теперь, наказать её и поставить в угол? Перестать использовать? Разработчики баг и так сами нашли и осознали, остальные понимают его смутно, могут разве что в чеклист проверок кода добавить.

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

Надеюсь, вы осознали факт, что бывают объективные причины, и не надо в первую очередь валить всё на QA.

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

Кажется, я уже несколько раз упоминал командную работу, что в данном случае означает, что менеджер помогает. Но сказать, что случилась беда и насколько всё плохо он должен.

Пожалуй я переборщил с термином огребут, ибо не сторонник я прилюдной порки, но сторонник того, что после выявления причин их обязательно необходимо донести до соответствующих лиц по возможности по одиночке.
И Ваши слова тоже подтверждают такую необходимость ибо в противном случае профессионал бы сказал, «да Я допустил просчет и не ожидал появления проблемы в этой части, однако были приняты меры по ее исправлению и учету в будущем, чтобы не допустить ее повторения». Любое «Мы» в подобный объяснениях — это перекладывание ответственности с себя на группу лиц, а группа лиц по определению не может ни за что отвечать.

«Мы», при командной разработке, очевидно, означает, что ни один из разработчиков не знал о проблеме. И, продолжая мой пример, это не просчёт, абсолютно никакой вины разработчиков нету. Наоборот, чуть ли не премию надо давать — смогли в короткие сроки найти проблему в чужой библиотеке и понять, как её обойти. Если же кто-то действительно сам багу сделал, то не обязательно его тыкать в багу носом, как нашкодившего котёнка. Если вы считаете, что вам такая терапия необходимо — то хорошо, но не всем она идёт на пользу.

Ну а стресс на работе для меня, это когда во время выполнения срочной работы мне настойчиво сообщают совершенно ненужные подробности, например о поседении волос, цене простоя и т.д. Грубо говоря, когда мешают работать. А на счет живых данных — осторожность в любом случае по умолчанию должна быть включена. Чай/кофе кстати работать не мешает, по этому те, кто считает, что в таких ситуациях нельзя неспешно пить чай/кофе параллельно с работой я тоже причисляю к источникам стресса, так как их мнение в отличие от чая/кофе тоже мешает нормально работать.

То есть саму ситуацию, когда вы в пятницу в 11 вечера уже пятый час пытаетесь понять, где же проблема, сервис, которым вы небезосновательно гордитесь, работает плохо, и вам до завтрашнего утра надо обязательно всё починить, стрессовой не считаете? Ок.

Ну и про чай. Про неспешное испитие чая я имел в виду именно неспешное испитие под беседу с коллегой о несовершенстве мира или колонизации Марса.

Информация

В рейтинге
4 908-й
Откуда
Россия
Зарегистрирован
Активность