Так а если блокирующий API, условно на минуту и у тебя 1000 rps создастся 60000 виртуальных потоков в томкате?
Читать полностью…я использую виртуальные потоки с котлин коррутинами для интеграции с блокирующим jdbc api
Читать полностью…с виртуальными потоками у тебя ограничителем становится семафор или крышечка на уровне инфры
Читать полностью…https://tomcat.apache.org/tomcat-10.1-doc/config/executor.html
Наверное сюда копать нужно. Интересно тоже может тут есть, кто использует уже на практике, расскажет.
Раздел Virtual Thread implementation.
org.apache.catalina.core.StandardVirtualThreadExecutor
Увидел вот эту запись про WebFlux, хотел уточнить про работу виртуальных потоков.
В Томкате например стоит ограничение потоков на 100, если использовать Spring MVC без виртуальных потоков, то одновременно с блокирующим API может работать всего 100 клиентов. WebFlux же позволял кратно большему числу клиентов работать с блокирующим API используя реактивные стримы.
Собственно вопрос, когда я подключаю виртуальные потоки в Spring MVC, то Томкат вместо своего пула потоков начинает использовать виртуальные потоки и сколько он их может наплодить?
Ну, я про то что абстрактный генератор байткода, если очень хочет, может таким образом достучаться до этих непростых api и играться с ними через бутстрап. Это далеко не то же самое, что и напрямую вызывать из клиентского кода, но оставляет возможность.
Читать полностью…Я скорее всего неправильно понимаю отдельные моменты из всей комбинации.
Есть некоторое количество функций/методов, которые не могут вызываться напрямую клиентским кодом. С самой необходимостью все понятно.
Непонимание начинается дальше и скорее всего кроется в том, что значит "внутри jdk". Насколько я понимаю - здесь опять же могу быть неправ, я только-только нашел свою палку, чтобы ковырять весь улей - и сам бутстрап, и его выхлоп представляет собой просто байткод. И вот этот запрещенный вызов Х так или иначе происходит в этом байткоде как оно произошло бы и в обычном коде, где-то есть вызов godForbid(), который (должен быть) доступен для вызова только внутри ограниченного числа торчащих наружу конечных методов.
Здесь я и не понимаю, в чем разница между новым ансейфом в share/classes и внутренней функциональностью jdk. Для меня это выглядит так, что даже если это вызов какого-то native метода, то у него так или иначе есть тот самый доступный для вызова интерфейс; можно его защищать хоть проверкой стека вызовов, но сам по себе он существует в той же вселенной, и его мало что отрезает от клиентского кода. Если же сам запретный код вызывается не на уровне байткода, а внутри цепочки вызова нейтивов, e.g. если сам бутстрап это native, и запретный вызов сидит где-то там глубоко внутри вообще без его проброса в api, доступный из байткода, то тогда я не понимаю как invokedynamic меняет ситуацию (такой нейтив можно было бы вызывать и без него - я здесь опускаю всю остальную разницу, естественно).
Я не особо хорошо формулирую мысли вообще по жизни, надеюсь что не законфузил ещё больше.
Ну, я про то, что за счёт этого rogue javac может заэмитить доступ к тому, к чему по идее не должен прикасаться.
Читать полностью…Спасибо. Я не понял до конца только два момента - с использованием приватных апи (потому что если предполагается, что javac не должен к ним иметь доступа, то здесь ему опосредованно приоткрывают дверь) и зачем это нужно рекордам (потому что value semantics открывает другую дверь к контрактам, зависящим от самого рантайма, e.g. equals через memcmp?)
Читать полностью…Все дальше чистое IMHO.
В моем понимании invokedynamic заменяет кучу прямых вызов методов с кастом переменных(особенно, если это Object). Плюс, можно подсунуть свой улучшенный метод, который сделали уже после компиляции.
"генерируя анонимный класс и его инстанс, сохраняя где-то последний"
Мне кажется у тебя без invokedynamic должно быть много таких классов по разный атрибутивный состав переменных
Например, String + Object один метода/класс
String + String второй метод/класс.
Если по старинке, то по идее норм как ты указал
https://www.youtube.com/watch?v=HWkVJkoo1_Q
Посмотри с 50 минуты, может чуть понятнее станет. Там как раз про invokedynamic. Если еще останутся вопросы, то Алексея тэгни, он есть в этом чате
Да, например почему нельзя улучшать перформанс invokedynamic в новых версиях jdk без перекомпиляции.
Я сейчас относительно серьезно, вопрос связан в том числе с тем, что я не до конца понимаю всю систему.
пробовал, малополезная вещь, так как протокол пг все равно блокирующий и создает процесс на коннекшен
+ r2dbc очень сырой и не развивается никак, в тестах jdbc быстрее, истинный смысл стриминга для крудов я не вижу, наверно если бы был r2dbc connector для постгреса в экосистеме кафки - это бы имело какой-то смысл
а так, jdbc - проверен временем, надежный, быстрый, поддерживается всеми тулами
так там идея буквально thread per request
родился -обработал реквест- умер
то есть в целом прям дофига может быть
Платформенные потоки, на которые происходит mount, ограничены определенным значением.
в jdk есть свойство, которое по умолчанию выставляет его в 256, насколько помню. Как с этим значением играется spring, не в курсе.
Но именно virtual threads, насколько мне известно, не предназначены для того чтоб их кешировали/ограничивали пулом.
Их может быть создано сколь угодно много и это нормально.
Не вижу, как. Абстрактному генератору байткода нужно будет как-то умудриться загрузить свой выхлоп привилегированным класслоадером или всунуть ему привилегированные lookup-ы, а кто ж ему даст, если он не в JDK. Только если пользователя аккуратно попросить --patch-module
или -Xbootclasspath
-нуть выхлоп, траст ми бро, джаст траст ми.
А "через бутстрап" дотянуться до опасного метода нельзя, потому что бутстрап тоже не дурак, и использует опасный метод только безопасно.
Кажется, краеугольный камень непонимания в том, что то, что генерирует bootstrap — это не просто байткод, а потенциально привилегированый класс/метод с байткодом. У этого метода могут такие же привилегии, как у кода JDK, а не пользовательского кода. Поэтому из него можно лазить в кишки JDK (как сама JDK лазит в собственные кишки), в отличие от. То, что JDK бутстрап исполняется в контексте JDK, даёт ему возможность генерировать привилегированный код, откуда вытекает возможность использовать кишки JDK в выхлопе.
Читать полностью…Bootstrap-ы в JDK дают javac-у публичную дверку — вот сюда ходи, мы всё сделаем как надо. Через эту публичную дверку нельзя сломать JDK, например. Другими словами, это высокоуровневая, публичная, безопасная дверка в JDK.
Вот скажем, реализации конката нужен метод, который аллоцирует неинициализированный массив. Если реализовывать продвинутый конкат прямо на стороне javac, то из байткода, сгенерированного javac, нужно будет к этому методу как-то доступаться. А как? Такой метод разрушает базовые гарантии безопасности языка, его нельзя класть наружу JDK от слова совсем, даже положив его в условный sun.misc и обмазав его всякими предупреждающими наклейками типа "не трожь, убьёт", потому что злодеи (или программисты библиотек, разбор падений на которых не будет их проблемой) на это предупреждение просто положат болт и всё.
А если этот метод лежит _внутри_ JDK, то его может использовать JDK-овый бутстрап-метод, отдельно гарантируя, что все использования этого опасного метода либо гарантировано безопасны, либо отдельно проверены.
К чему, пардон? Ещё раз, всё что эмитит javac — это публичный байткод. С точки зрения JVM вообще не важно, кто этот байткод сгенерировал, ему доступно только то, что лежит в public API. javac с этой точки зрения на таких же птичьих правах, как и любой генератор байткода, типа самописного rogue на условном ASM.
Читать полностью…javac генерирует публичный байткод, байткод приложения. Этот байткод по определению имеет доступ только к публичным API. У javac нету никаких секретных дверок.
Рекорды реализуют свои hashcode/toString и проч через indy, потому что это удобно. Это _ключевая идея_ в ответе на вопрос "почему нельзя просто эмитнуть базовый байткод прямо javac-ом?". Можно! Но удобнее эмитнуть indy и раскрыть его в рантайме, потому что см. выше.
В JDK invokedynamic (indy) главным образом используется для вынесения решения о том, как выглядит итоговый байткод для конкретной фичи языка за рамки трансляции в байткод javac-ом. Рантайм спрашивают по месту, выполняя нужный bootstrap method. Это позволяет:
1. Делать оптимизации в райнтаме, не меняя байткод (т.е. не требуя рекомпиляции javac-ом), а только докручивая bootstrap-методы
2. Доступаться к внутренним API самого JDK, которые открыты внутренним бутстрапам, но не сидят в public API. Коду, который эмитит javac, можно лазить только в публичный API. Indy позволяет сделать публичным только точку входа в bootstrap method.
3. Выбирать ровно тот байткод, который хорошо работает с конкретной версией рантайма, то есть то, что JIT хорошо понимает. При этом устраняется NxM проблема (N версий байткода, M версий рантайма), потому что рантайм эмитит нужный ему байткод сам.
4. Предкомпилировать и переиспользовать общий байткод, который может забустрапить несколько indy сразу. Это и фича конкретных бутстрапов, и более общая, типа сохранения результатов бутстрапов в CDS.
Сигнатурный полиморфизм — это только бонус на фоне этих достоинств.
Поэтому чем дальше в лес, тем больше JDK-овых фич будет полагаться на indy: удобство этого инструмента покрывает его недостатки. На него уже что только не опирается: и лямбды, и конкат, и методы в рекордах, и паттерн-матчинг, и ещё чёрта в ступе.
Алексей давно не забегал ни сюда, ни в соседнюю байтоперерабатывачную (
С invokedynamic я судя по всему просто неправильно воспринимал его работу. У меня сложилось ощущение, что эта история исключительно про дактайпинг, в то время как он подразумевает бутстрап сам по себе, и оттуда вытекает в лямбды и места, где ожидается потенциальное серьёзное улучшение кодгеном из base class library. Всё это теоретически можно было бы сделать - сейчас игнорируем улучшения, удобство и размер байткода, я про вопрос эквивалентности - старыми добрыми заржавевшими подходами, просто генерируя анонимный класс и его инстанс, сохраняя где-то последний (пока не смотрим дальше constant call site) и затем вызывая его метод в тех местах, где у нас в настоящее время висит invokedynamic, так?
Если мы говорим про бутстрап методы и возможность разного кодгена, то ну ээээээ почему бы нам тогда вообще .java-файлами приложения не распространять и пропускать стадию байткода на диске
Читать полностью…ты ишешь какое-то более внятное объяснение, чем "мы можем использовать invokedynamic в байткоде, улучшать перфоманс в новых версиях jdk, при этом джаву не придется перекомпилировать, и тот же самый байткод будет работать быстрее?"
Читать полностью…Спецы по greenplum, подскажите есть ли нормальные бенчмарки по инсертам/обновлениям через copy, pxf, gpfdist и как они измеряются при добавлении сегментов
Читать полностью…