ЗN>В случае Java, я думаю, сделано просто какого-то явно лишнего кода. Или в условиях очень коротких сработок на один клиентский запрос с длительными ожиданиями между ними — сделана какая-нибудь глупость типа персональной нити на каждого клиента. Иначе бы такой суровой разницы не было.
Именно в том и дело, что в Java/C++ и прочих "закатах солнца вручную" очень легко выстрелить себе в ногу. Вот в самом деле, персональная нить на клиента — это же, черт подери, удобно, и очень правильно! И, собственно, так и должно быть (более того, должно быть две нити на клиента, одна на вход, другая на выход, in/out pipes). Потому что это точно воспроизводит всю коммуникационную специфику. Неспроста же это решение возникло в телекоме. Обмен сообщениями. Просто, понятно, гениально.
N>Но это надо смотреть реализацию в деталях: что делается и как.
Как обычно. Дьявол в деталях. И в уровне разработчиков. То, что десяток профессионалов сделют на Эрланге, может быть недоступно сотне "обычных порошков". Для меня, кстати, это совсем недавнее открытие. Раньше я как-то и представить не мог, что один разработчик может быть на порядок более производителен, чем другой. То есть, раньше, в моем понимании, команда из пятерых человек по определению сделает больше, чем один гений. Вынужден признать, что глубоко заблуждался.
N>Вот например RabbitMQ борется с такой проблемой:
Как обычно, у любой проблемы есть варианты решений. Хотя для начала надо понять, почему у них эта проблема существует вообще.
1. Почему у writer'а длинная очередь?
2. Почему selective receive optimisation не работает для их случая?
3. Почему они вообще используют gen_tcp?
Могу лишь предположить, что:
а) переписывать старый код дорого
б) им нужно поддерживать старые версии OTP, или неподходящие для их софта ОС (ту же Windows)
в) нет большой нужды что-то улучшать в этом коде
Ибо если б нужна была, достаточно было бы просто перебраться на socket API, который выполнен в виде NIF и не страдает от указанных недостатков.
Я бы еще понял, если бы они страдали от странностей реализации TLS. Вот там да, мягко говоря, все очень и очень грустно, по куче разных причин. Что уж там, 3 последних PR я делал как раз вокруг TLS, ибо там и баги, и тормоза, и вообще — так делать не следовало с самого начала. Но "переписать с нуля" было бы еще менее осмысленным шагом, ибо это была бы уже четвертая реализация
N>1. Да, ребята молодцы, что для решения проблемы они полезли в обход аж двух слоёв стандартной библиотеки
Думаю, здесь было бы куда более логичным описать проблему более предметно. И вместо "обхода двух слоев" добавить нужную фунцкиональность. Но для этого им бы сначала пришлось разобраться в существующей. А вот это всегда и для всех было проблемой. Что уж там, сколько лет я пытаюсь подвинуть процесс интервью в направлении "проверять как кандидат умеет _читать_ код", но воз, увы, стоит на месте — все так же требует _писать_ код (который писать не нужно).
N>2. Нет, надо было искать чудо и делать, чтобы очередь никогда не превышала K сообщений, где K < N. Как это делать — да хоть через ETS, которую наполняет другой процесс. Публичная ETS (потому что удаляет другой процесс, чем добавляет) не страшна, все свои.
За такие "архите-крутные" решения вынесу порицание. И вообще, к моему страху и ужасу, кроме Вирдинга да еще пары человек понмания какие ужасы несут нам ETS, почти ни у кого нет. Как тут не вспомнить Хаскел, где усилие было приложено в нужном направлении, и ETS попросту нет (в том виде как они есть в Эрланге).
N>3. Надо было сидеть и страдать. Нефиг тут неуправляемые входные потоки принимать на процесс. TCP приёмник нормально контролирует, а заторы возникают по дороге? Пофиг, у меня всё работает (tm).
Этот вариант я не понял. Что именно предлагается? Разделить на два процесса, где у одного очередь и flow control, а второй непосредственно пишет в сокет? Да, так делают, да, нормально работает, но да, костыль. Но вообще эти страдания не совсем логичны. Впрочем, хорошо уже то, что у них таки есть разделение на r/w. Потому как куда более суровы страдания тех, кто в одном процессе все это делает, а потом жалуется, что gen_tcp:send() не возвращает управление пока данные не уйдут хотя бы в kernel send buffer.
N>4. Вы неверно понимаете задачу и вообще у вас плохой дзен, становитесь ёжиками. Детали не интересуют, я стратегию разрабатываю.
N>5. Иное (интересно, что?)
Пожалуй, что "иное" — просто используйте socket. Если его нет в вашей версии, — портируйте. Вполне нормальная практика backport'ить что-то из старших версий, скажем, мы в древние времена бэкпортили crypto, чтобы работало с аппаратным ускорением (через УМЗ), а не как в R16B.
N>1) Пакуем всё в один тарболл вместе с рантаймом, зависимостями и рабочим кодом
Так ведь это и есть release (он же target system). Где-то еще так с начала 90х
N>5) failover, takeover, relup? Дядя, ты с кем сейчас разговаривал? У нас свои средства кластеризации и надёжности в кластере (90% — просто общая SQL база).
Традиционная проблема же, "нам некогда учиться, нам надо вчера", в итоге велосипедостроение в полный рост, tech debt, и — свой вариант, но очень незрелый, того что есть в ОТР.
Классика жанра. Очень немногие способны разобраться, понять как сделано, как надо, какие грабли были. Нет, вместо этого надо скорее делать, чтобы потом просто совершить еще один круг, еще один прыжок на месте, сделать свой Эрланг, с блекджеком и женщинами.
N>И на него тогда даже смотрели "а он сможет обеспечить нормальный relup на месте, без рестарта, при своей паковке?" и на версиях тех времён однозначно не сложилось.
Может быть. Я в 2012 этим не занимался. Но были уже тогда systools. Но да, неудобные — и правильным вариантом было бы просто исправить. Ибо ведь open source. Это и есть подход, который я исповедую. Сначала разберись, потом пойми, потом осознай, почему так, — потом исправь и сделай мир лучше. Дай другим результаты твоего труда. Используй синергию этого процесса, объедини усилия.
Но да, это требует усилий.
N>Нет, для себя мы её решили — костылями различной кривости.
Может, в этом причина недовольства?
N>В спокойной обстановке на участке NMU — GL поток сообщений в десятки раз меньше входного потока NMU (то есть тысячи, если не сотни, в секунду, уровня "тут всё спокойно, тангаж, крен, рысканье в норме, температура 36.6"), при проблемах — может подскакивать до равного потока (считаем, те же 100K mps). Работа при пиковой нагрузке, соответственно, критична (должно быть всё гладко-линейно и должен ещё быть запас производительности).
Это же невозможно по определению. Или вы должны быть overprovisioned, чтобы соблюдать гарантии, или должна быть load shedding логика для защиты от перегрузки, или — backpressure.
"Все уже украдено до нас":
https://ferd.ca/handling-overload.html
N>2) Если ему хоть иногда надо делать синхронные вызовы (gen_server:call) и соответственно сразу ждать отвёт — всё, суши вёсла
Хаха, как знакомо, все с тем же Вирдингом общались на тему "кто же это придумал gen_server:call и какие кары ждут его в аду"

Все правильно: как только нарушается стройная концепция ("процессы обмениваются сообщениями") и приходит императивный девелопер "нам нужно сделать RPC", как все сразу начинает работать не так, как задумано. Embrace concurrency, adopd asynchronicity, и так далее. Пока это не случится, будут все те же одинаковые проблемы с блокировкой процесса там, где не следует.
N>: из накопления входной очереди выше 10-20K сообщений он не способен уже выйти. Граница неточная, но, похоже, связана с размером кэша процессора.
Прочитав еще пару комментариев ниже, и увидев, как другие участники восхищаются скоростью постановки диагноза, просто обязан прокомментировать. Во-первых,
отослать к моему выступлению на прошлой code MESH, — как раз на тему "in god we trust, all others must bring data".
Во-вторых, конечно же, у меня есть куда более простое, логичное и понятное объяснение, почему это происходит, ибо — я в теме разобрался чуть менее поверхностно. Допускаю, что у вас на тот момент не было никого, что мог бы просто воспользоваться gdb/perf/fprof/eprof/cprof, и понять, что дело не в кэше, а в том, как работает GC. Но да, что занятно, Rick Reed в свое время тоже наступил на сию граблю, но на то он и Rick Reed, чтобы разобраться. Я тогда еще и рядом не стоял. Могу лишь гордится тем, что учился у таких людей.
Так вот, возвращаясь к вопросу, — возможно в древних версиях, которыми вы пользовались, еще не было off-heap message queues, поэтому и случалась death spiral, когда с ростом количества сообщений в очереди GC становился все более и более дорогим, что вело к еще более быстрому наполнению очереди, что вело к еще более медленному GC, и так далее.
N> Временное переполнение, безвредное в других условиях, становится фатальным (надо только рубить процесс).
Кто хочет, ищет причины. Кто хочет — решения. Мы нашли решения: во-первых, добавили патч для flush message queue, во-вторых, допилили GC для более удачной работы с длинными очередями, в-третьих, когда доделали off-heap mq, просто перелезли на них.
N>Вот теперь я хочу послушать Ваши предложения по исправлению этих проблем в пределах текущих возможностей Erlang.
Надеюсь, я ответил. No fate but the one we make. Если что-то сейчас в Эрланге не так, как нужно, это либо просто не было нужно до вас (и тогда — просто сделайте PR), либо... вам это не нужно, просто нужно разобраться, как оно на самом деле должно быть.
N>Нет. Backpressure вообще недопустим <...> Остановить агентов мы были в состоянии. Реально они сами останавливались, не получив команды "даю разрешение на 5 отчётов".
Или я чего-то не понимаю, или... это как раз и есть backpressure (в самом простом и классическом варианте, т.е. credit control. Странно, что это вы считаете "хаком". Это вполне легальный, и один из самых простых в реализации, способов. В конце концов, Ulf Wiger еще в 2010 (на деле, в 2005, но опубликовали позже)
с теоретической стороны это рассмотрел. Позже, в том же Elixir, Jose Valim сделал аналогичный GenStage. Да что там, реализаций немало.
И. Справедливости ради, это же и есть holy grail. SEDA, и все эти akka streams, и все это reactive programming, — все аналогичные data flow pipelines, все это отнюдь не ново! Все уже было, и whitepapers более чем навалом, и реализаций. Если уж вы работали над "Ломоносовым", это ведь в МГУ, как могло так получиться, что вы не были знакомы со всеми работами в этом направлении? Уж на что моя должность прикладного характера, но даже я с ними знаком. Ибо без такого знакомства я был бы обречен написать очередной worker pool.
N>И снова домыслы и критика "обезьян". Но это я отложу на следующий заход.
Давайте, очень жду. Чем же так был нужен global, чтобы вот без него никак.
SD>>А надо было обсуждать с Lukas Larsson, Kenneth Lundin, Rickard Green, Sverker Eriksson, Kjell Winnblad. Круг, действительно, узок, и он не включает ни одной из указанных выше фамилий.
N>Общением с кем-то из core team занимались другие коллеги. Успеха не добились.
Что такое core team?
OTP team, у них нет "core", есть VM, есть PS, и есть еще один человек сбоку. И так уже лет... пятнадцать. И вот это, да, проблема, слишком мало драйверов роста.
Не знаю, почему не удалось добиться успеха. У нас отлично получается.