All streams
Search
Write a publication
Pull to refresh
4
0
Send message

хорошие оптимизирующие компиляторы можно сделать только для языков относительно низкого уровня типа C/C++. Для современных ООП языков типа C#, Java, Python, боюсь оптимизация получается довольно посредственной.

Собственно, вся суть С++ в том, что это С + ООП (на практике; есть, конечно, любители целиком шаблонами писать). И вот тут, как раз, рантаймы типа Java выигрывают в плане именно компиляторных оптимизаций под ООП, т.к. один из основных оверхедов это вызов виртуальных функций, и статический анализ здесь проигрывает динамическим рекомпиляциям: например, при вызове интерфейсных методов рантайм может на основе истории вызовов понять, что вот в этом конкретном месте (callsite) по факту под интерфейсом скрываются всего два конкретных класса (хотя интерфейс реализуют 9000 классов), и заменить дорогие вызовы через виртуальную таблицу (а это функция по указателю, что у многих процессоров сбивает branch prediction) на простое сравнение "если это класс А, то сделай jump сюда" (так называемый callsite cache), а может пойти дальше и полностью девиртуализировать вызов (если класс один), что сразу же позволяет активировать кучу оптимизаций типа инлайнинга. Такое ручками делать в постоянно развивающемся проекте - такое себе удовольствие. Но такие рантаймы обычно всё равно медленнее С++, просто потому, что в по дизайну в них чаще всего присутствует также сборщик мусора и отдаётся предпочтение by ref-объектам вместо value types, т.е. страдает memory locality. Не могу вспомнить, чтобы был язык с продвинутым JIT, но без GC. Было бы интересно на такой посмотреть.

Можно и по-другому аргументировать - оптимизирующие компиляторы, в т.ч. profile-guided компиляторы (особенно с динамической рекомпиляцией), идут в направлении оптимизации под конкретную нагрузку, а значит оптимизация руками будет всё менее и мене релевантна, т.к. сложно заранее предугадать, какая будет нагрузка (и какая там конфигурация сервера в данный момент, т.к. у каждого свои особенности). Да и сейчас, если дать написать ассемблер обычному разработчику, его код скорей всего будет менее оптимальный, чем код современного оптимизирующего компилятора.

Имхо, больше выгоды даст написание cache-friendly кода, правильный выбор алгоритмов (O(1) вместо O(n)), а это можно сделать и без ассемблера.

Насколько я помню, timeBeginPeriod меняет точность таймеров (частоту тика) во всей системе в целом, не только в текущем процессе. Т.е.:

1) сильнее начинает жрать батарею ноутбука, т.к. процессы просыпаются чаще

2) часть программ может упасть с ошибками, если они ожидали resolution в 16 мс (видел багрепорты)

Разве это не то самое переизобретение из комента выше?

В локальной БД хранится только outbox сервиса, без доп. логики. Если у нас N сервисов, заинтересованных в событии, то нам нужно N инбоксов, для каждого сервиса. В той же БД их невозможно хранить (т.к. БД разные), и на каждое обработанное событие для каждого сервиса также нужно поддерживать состояние (ack или не-ack). Профит в чём: 1) отказ продьюсера (его самого или его БД) не останавливает обработку, т.к. консьюмеры независимы и работают со своими копиями сообщений 2) гарантирует целостность данных 3) уменьшается связность сервисов, т.к. продьюсер не знает своих обработчиков. RabbitMQ довольно стабильная штука, и больше вероятности упасть не ему, а какому-то кастомному сервису одной из команд, напр. после неудачного релиза (а их овердохрена), поэтому и выносится это на редко изменяемый стабильный внешний сервис. Как я уже сказал, это полезно в основном при микросервисной архитектуре для повышения масштабируемости и отказоустойчивости, иначе для более простых проектов это явный оверинджиниринг.

система усложнилась

У нас всё ещё сложнее :) Каждый аккаунт это отдельная организация с тысячами пользователей (tenants), и чтобы избежать ситуаций, где одна большая организация забивает очередь событий 9000-ми событий и останавливает обработку для более мелких (т.к. они будут ждать своей очереди), у нас есть ещё одна прослойка, которая диспатчит события "справедливо", т.е. распределяет их порциями, чтобы у каждого аккаунта обработка продвигалась равномерно.

Это всё придумано не просто так "чтобы было" и является эволюционным решением конкретных проблем бизнеса (до этого был простой монолит без RabbitMQ, но перестало вывозить); если вам в ваших проектах профита нет, то не знаю, зачем вам доказывать профит :) Он есть, но решается для конкретных задач. Можно жить и без брокеров, но иметь в виду как инструмент всё же стоит :)

Я имел в виду падение именно консьюмера (подкорректировал оригинальное сообщение) - сообщение тогда потеряно, т.е. гол в пользу RabbitMQ.

Что касается продьюсера, то верно замечено, что если мы упали после сохранения в БД, но до добавления события в очередь RabbitMQ, то мы тоже потеряем событие (имею в виду полное падение продьюсера, где retry невозможен). Для этого используется идиома transactional outbox - информация о событии создаётся и сохраняется в локальную БД в той же транзакции, что и бизнесовая операция на запись. Т.е если мы упали, то откатится вся транзакция сразу (ни изменений, ни событий). А если транзакция успешно закоммичена, то наличие события в БД гарантирует успешность/транзакционную целостность. Далее отдельный поток извлекает такие события из БД и кладёт в RabbitMQ с ретраем - т.е. мы гарантируем, что событие будет доставлено, в том числе если временно отвалится брокер. Плюс брокера в том, что это отдельный сервис, через который можно подключить по отдельной очереди на каждый сервис (для параллельной обработки), и он имеет из коробки протестированные временем инструменты для менеджмента таких очередей. Обычно польза чувствуется только если проект придерживается микросервисной архитектуры, где сервисы изолированы и с собственными БД, иначе можно, конечно, обойтись и без RabbitMQ, т.к. в монолите у нас и так есть доступ к персистированным событиям.

Также замечено верно, что RabbitMQ в таком случае становится узким горлышком (если он упал, то встанет вся обработка), но с таким же успехом может упасть и БД монолита. Тут главное, как по мне - возможность продолжить работу после падения как ни в чём не бывало (что позволяет персистирование очередей) и сам механизм exchanges/queue, который есть из коробки. Конечно, тут магии нет, и можно написать свой сервис событий, но можно использовать и готовый инструмент, проверенный временем.

Если упал процесс обработчика, то теряется контекст (теряется событие), и перебор циклом не поможет, так как мы не знаем, с чем работать. Конечно, можно сохранять события и в БД, но тогда нам придется самим переизобретать то, что уже умеет RabbitMQ.

У нас RabbitMQ используется в качестве событийной шины для общения между сервисами. Сервис А генерирует событие, оно кладётся в "exchange", который раскидывает сообщение по подключённым очередям сервисов B, C, D и т.д., которые в нужном им темпе извлекают события и как-то их обрабатывают. Сервис может таким образом реагировать на свои же события, т.е. получаем асинхронную обработку. С помощью очереди можно ещё реализовать асинхронные команды. Тут плюс в том, что очередь персистируется, и если сервис упал и не успел сделать ACK, то произойдёт retry (т.к. останется в очереди), что полезно для отказустойчивости, плюс там есть свои плюшки для мониторинга и работы именно с очередями... Но есть и свои минусы - если память кончается, то он заблочит все соединения (начнут висеть без ответа) и обработчики должны быть идемпотентными из-за at least once delivery. Если инстанс приложения один и объёмы небольшие, можно обрабатывать события сразу в том же запросе/транзакции.

>консамер

А еще лучше консьюмер

Так скажут, что это была ошибка, которую тут же исправили. Можно разве что судить за упущенную выгоду, но это ещё доказать нужно.

Вызовы Close внутри using выглядят лишними.

Интересно потом узнать, упала ли конверсия в целом. Ну вот например, хотел зайти поглядеть чего да как, но тут пишут надо чего-то регистрироваться, аккаунты какие-то. Хотя раньше заходило без проблем. Так и вышел, т.к. не очень-то и хотелось :)

Зашел на сайт разработчика сайта - у самих нет сертификата. Прошелся по кейсам клиентов - у половины тоже нет, при том что где-то есть вход/регистрация. Заинтересовало, откуда такая странная студия появилась. Выяснил, что их руководитель - юрист, который делал детский сайт о президенте на на kremlin.ru, сайт о патриархе Кирилле, в основном православные проекты. Сама студия названа в честь арабского правителя 6 века Арефы Эфиопского, которого в одной из войн сжёг омиритский царь-иудей Дунаан. В какой-то момент, читая википедию о христианских великомучениках, я задумался, "а при чем тут, собственно, процессоры Эльбрус", и прекратил исследование :)

А почему русский? Слово из английского, и там stake и steak тоже звучат одинаково.

Stakeholder и stockholder это разные термины. Stockholder это владелец акций, а stakeholder это заинтересованное лицо.

Элливита" - явно не греческое слово. Ходит под флагом Маршалловых островов (читай - США)

Что-то вы не то нагуглили. По ссылке у вас Элевит. Элливита ходит под флагом Греции: https://www.myshiptracking.com/vessels/ellivita-mmsi-239615000-imo-9171151

И тащем-та, по-гречески Греция это "Эллада", так что вероятно в Элливита тот же корень.

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

Такой подход обычно уже реализован с самим OutOfMemoryException. Когда происходит OOM, нужно создать объект типа OutOfMemoryException и инициировать завершение программы. Но как это сделать, если памяти-то нет? Поэтому объект и сопутствующая память резервируются заранее при старте рантайма. Идея не нова (в рантаймах можно встретить похожее и для обработки stack overflow), но оно годится только чтобы более-менее адекватно упасть (записать в лог, например), продолжать работу не стоит.

>Goland

А что не так с этой замечательной IDE от JetBrains?

Information

Rating
Does not participate
Registered
Activity