Комментарии 143
Это не евангелист какой-то паршивыйвентилятор на полную! :)
Есть предчувствие, что так очень легко нарваться на лекцию jbaruch, касающуюся введения в профессию и чистоты морального облика хаброавтора. Особенно учитывая, что сегодня интервью с программным комитетом devoops, и он там будет. Немного боязно даже.
Все лайчонки пойдут на создание нового контента. Спасибо.
Фуу, такое чувство что общаешься исключительно со школьниками средних классов. «Хардкор» в подаче для самых маленьких?)
Не предчувствуйте, с Барухом вы как бы из одной лодки и конфликта интересов быть не должно!
Ну я сам школьник средних классов — люблю потреблять именно вот такой контент. Как думаешь, что я сейчас смотрю в перерыве между работой? "Макса 100500" на фоне леопардового ковра. Сорянчик. Делал как для себя :-)
Ну я сам школьник средних классов
Надеюсь что не на полной ставке по трудовой оформлен, иначе нарушение ТК!)
Будет потом как в меме про журналиста и ученого… «Хабр окупировали школьники»
Так они его и оккупировали. Собственно, статьи про кишки OpenJDK для того и нужны, чтобы постараться повернуть колесо в положительную сторону: больше качественного контента про программирование — больше адекватных людей — которые генерят еще больше качественного контента. Каждый боец нужен и важен на фронте.
Про цели можно поспорить, лишь пытаюсь донести мысль что такая подача контента фокусирует ваши усилия на тех кого описали. Кто во что верит, тому и такая целевая аудитория.
Уровня развития школьника вполне должно хватать, чтобы мочь программировать на Java или даже C++ вполне осмысленные вещи.
И очень-очень скоро все эти школьники станут нашими коллегами, нашими начальниками, нашими товарищами.
Пусть привлекает. Если они сюда набегут — это будет праздник, обсуждение файберов пойдет куда живее
Это как практикующих медиков учить по «Стоматология для чайников».
А если без юмора, поскольку твои работодатели спокойно относятся к этому «прыщавому» сленгу, клянчанью лайков, мемам на каждом слайде и платят зарплату за такой маркетинг и PR. То можно сделать выводы, что ради увеличения прибыли, взяли партийный курс на развлечение и завлечение людей далеких от официальной целевой аудитории конференции — геймеров, школьников и их родителей. Запасаюсь попкорном и наблюдаю в стороне…
Хочешь сюрприз? Я на эту статью потратил свои личные выходные, и никто мне ничего за неё не заплатил. О чём, кстати, сказано в дисклеймере к статье.
У меня очень серьезные консёрны на тему, что если я буду ещё и стримить с приличной периодичностью, то учитывая работу — когда мне спать? Подготовка видосиков требует поразительно много усилий. Похоже, спать придется перестать.
Я сам геймер, вечерами постоянно играю в Overwatch (и хочу попробовать Quake Champions, а вот PUBG и батл рояли вообще не переношу) и время от времени устраиваю уютные стримы на своем Фейсбуке, вечерами после работы залипаю в Твиче, IRL тусуюсь в стримерской тусовке. Даже с летсплейщиками. Для меня именно такой формат наиболее понятен и приятен.
Поэтому когда выдалось время сделать нечто для души, а не по работе, я стал делать именно то, что стал бы смотреть сам. А теперь сорянчик, надо шлёпать — пересмотреть, чего там Дрю записал за эту пару дней.
Хочешь сюрприз? Я на эту статью потратил свои личные выходные, и никто мне ничего за неё не заплатил. О чём, кстати, сказано в дисклеймере к статье.
Респект! Не горюйте, вернется премией за KPI после сезона конференций. Материал стоящий, но подан сомнительно.
Еще есть минимум пара-тройка способов как сэкономить время на полезную и интересующую вас работу, но думаю сами догадаетесь.
По поводу остальной информации — она лишняя для меня, вместе со всем этим «сально-прыщавым» сленгом) Могу только посочувствовать вам и вашим родным по этому поводу. Но в принципе, все написанное вами подтверждает мои предположения о стратегии работодателей.
Никак не могу найти хорошего материала, когда какую технологию использовать и как.
Я правильно понимаю — если читаешь много или пишешь в сеть/файл — лучше использовать fibers/async/coroutines + пул потоков (к примеру, как делает Netty + Executors.newFixedThreadsPool()); если же обрабатываешь много данных (к примеру, эмуляция игрового мира), то лучше разбить всё по обычным потокам?
Был бы безумно рад, если б кто кинулся какой-нибудь книжкой-умной статьёй :)
Цитируя StackOverflow:
A Fiber is a lightweight thread that uses cooperative multitasking instead of preemptive multitasking. A running fiber must explicitly «yield» to allow another fiber to run, which makes their implementation much easier than kernel or user threads.
A Coroutine is a component that generalizes a subroutine to allow multiple entry points for suspending and resuming execution at certain locations. Unlike subroutines, coroutines can exit by calling other coroutines, which may later return to the point where they were invoked in the original coroutine.
A Green Thread is a thread that is scheduled by a virtual machine (VM) instead of natively by the underlying operating system. Green threads emulate multithreaded environments without relying on any native OS capabilities, and they are managed in user space instead of kernel space, enabling them to work in environments that do not have native thread support.
Я правильно понимаю, получается, что корутина прерывается только в момент await, а fiber — в момент, когда этот самый fiber говорит «я уже доделал»? Из статьи не особо понятно, чем этот подход отличается от конкретно корутин :)
Волокно (fiber) же — это легковесный поток. У него есть свой стек, и приостановиться он может на любом уровне вложенности. Достоинства волокон — при поддержке стандартной библиотеки их можно сделать полностью прозрачными для программиста (неотличимыми от потоков). Недостатки волокон — без таковой поддержки они получатся половинчатыми, плюс для них нужно выделять стек (последний недостаток как раз пытаются тут устранить хитрым копированием).
- много IO, мало вычислений — lightweigh треды
- много вычислений, мало IO — обычные треды
- очень много вычислений — смотреть в сторону горизонтального масштабирования
Но в реальном мире простого не бывает, поэтому зависит от ситуации :)
Smalltalk, 80-e. Green Threads, Continuations «из коробки»...
Если просто погуглить + java + continuations, то вы на первой же странице увидите, кроме Loom, еще парочку проектов, один из которых был сделан аж в 2007. И что-то никто особо не впечатлился. Вопрос — а почему, собственно, в этот раз должно взлететь? В чем разница-то, если в этом проекте работы осталось начать да кончить?
Сейчас в Kotlin сделали корутины и впечатлились… ну, можно сказать, все кто может использовать Kotlin. Впечатлились все. В golang есть горутины — и это одна из топовых причин, зачем вообще юзать голанг.
Что касается языка Java. Нормально без хаков в рантайме этого никак не сделать, и все кто делал — получали что-то наполовину нерабочее. В том же котлине вообще не подразумевается, что есть какой-то 20-летний легаси, который надо заставить работать без изменений и пересборки. В той же алибабе это хак виртуалки, причём прямолинейный и дорогой, и они жутко мучаясь поддерживают форки, насколько понимаю.
Здесь же это официальный проект компании Оракл, которая выделила на это лучших инженеров и бабло. Его на фуллтайм ведёт человек, который уже однажды сделал Квазар и имеет успешный опыт. Плюс поставлены вполне конкретные задачи — сделать не как попало, а сохранить главную отличительную фишку платформы Java — совместимость с legacy кодом. Все несовместимости в API, все корнер-кейсы — к этому относятся не как к мелочи, а как к важнейшим аспектам вопроса.
Плюс в целом, дозрела культура разработчиков. Пришло глобальное понимание о нужности таких штук.
Ну вот скажем пост от 2005 года.
>Нормально без хаков в рантайме этого никак не сделать, и все кто делал — получали что-то наполовину нерабочее.
Я боюсь, что и с хаками это нормально сделать сложно. Не так чтобы работало, а так, чтобы было совместимо с легаси.
>Здесь же это официальный проект компании Оракл, которая выделила на это лучших инженеров и бабло. Его на фуллтайм ведёт человек, который уже однажды сделал Квазар и имеет успешный опыт.
Ну, к сожалению в общем виде деньги еще ничего не гарантируют. Опыт — это чуть лучше, но это ограниченный опыт одного человека. Или даже группы.
>и в большой картине всего это, скорее, достижение.
Ну да, и? Но я вот впервые от вас слышу про квазар, что как минимум говорит о том, что по популярности ему пока далеко даже до котлина. Поймите меня верно, я только за то, чтобы встроить continuations, но меня смущает тот факт, что оракл запилил уже 10 версию JDK, а народ при этом массово сидит скажем на 8, и никуда, заметьте, мигрировать не спешит. И этот народ — например все, кто на хадупе, ага. Далеко не самые глупые люди. То есть, их способности в целом, как компании, прогнозировать нужность тех или иных фич — они далеки от идеала, не потому, что они там глупые, а потому что задача уж очень сложная — сохранить совместимость, и угодить всем.
сохранить совместимость, и угодить всем.
да, поэтому этой задачей и занимаются лучшие в мире разработчики из компаний Oracle, RedHat, IBM, и других разработчиков OpenJDK. Они сделали Java 8 такой, что на неё очень скоро переползли все. И да, когда появлялась Восьмерка, точно так же ныли: "да мы ещё на Шестёрке, куда столько версий"
я тоже когда-то жил в каком-то узком мирке, наполненном людьми ленивыми и очень боязливыми, уставшими от жизни. Понимаю, о чем вы. К несчастью, эти выгоревшие люди имели большие тайтлы вроде "самый главный старший архитектор всего" или "директор директоров по управлению управлением". И они рассказывали эти унылые душные басни о том, что Java 6 это наше всё, а с Hibernate x.x.y на x.x.(y+1) переходить — это капец какое предприятие. Проблема не в технологиях (которые на самом деле дают большие возможности делать крутые вещи — например, файберы экономят огромное количество денег), проблема вот в таких людях
и вот знаете что, я в 2018 у меня всё замечательно, а половина этих нытиков или обанкротилась или ушла на пенсию и теперь пасёт гусей
так что, наверное, я не самый верный человек для того, чтобы обсуждать как всё плохо, и что ваше большое начальство рассказало о том, что вы вечно будете на Java 8. Чемодан — вокзал — современная клёвая компания, которая сможет воспользоваться преимуществами новейших разработок в JDK, всё что могу посоветовать :-)
а на JDK 10 переходить действительно не стоит. Сейчас JDK будут обновляться либо раз в полгода (для обычных компаний), либо раз в 3 года LTS (для совсем кровавых замшелых ынтерпрайзов). И тем и другим сейчас нужно переходить на JDK 11, это новая точка отсчёта для всех
Расскажите это авторам хадупа. И не надо выдумывать всякую фигню про начальство, если вы просто не в курсе — это не зазорно, уж поверьте.
Зачем им это рассказывать, они уже давно портировали его на jdk9, а сейчас полным ходом переходят на jdk11, судя по их же джире.
Fix Java 9 incompatibilies in Hadoop
Status:OPEN
Resolution: Unresolved
Affects Version/s:3.0.0-alpha1
Fix Version/s: None
Component/s: None
Environment:Java 9
Вы хоть открыли ту ссылку, которую давали?
Сейчас в OpenJDK незакрытых багов из основного списка — двадцать тысяч, из них три с половиной тысячи относятся к стабильной версии — JDK 8 (конечно, ни одной P1, 13 штук P2, но уже 751 P3 и тысячи по мелочи).
Это вы еще не видели, сколько их в JDK 11!
Наличие открытых багов не является причиной для неиспользования.
То что вы прислали — это не баг, это Task по устранению несовместимости. И она не сделана (как и связанные задачи, кстати). Более того, судя по пустым Fix Versions — ее даже не планировали пока сделать, т.е. не известно, в какой версии она будет готова.
Я уже молчу про то, что Affects Version/s: 3.0.0-alpha1 — т.е. если даже и начнут исправлять — то вероятно исправят в третьей ветке, которая промышленным кластерам в ближайшее время не светит.
На основной странице документации явно написано, что протестированные версии JDK — это 7 и 8, с явным указанием конкретных билдов. Ровно тоже самое пишут на сайте Cloudera.
Я непосредственно являюсь хадуп разработчиком, и для нас никакой поддержки Java 9 пока нет, и не предвидится. Моя личная оценка — пройдет еще года два минимум (наш пром кластер, как и остальные, пока работает на версии 2.6 хадупа, в планах в лучшем случае миграция на 2.8), и в первую очередь потому, что это нафиг никому тут не нужно, ибо никакого профита даже не обещает.
У меня никогда в жизни особых проблем с этим не возникало. В смысле, я постоянно сижу на альфа-версиях всего, и да — очень часто бывает что в Spring после апдейта отваливаются нужные фичи и приходится чинить их дрожащими руками долгими одинокими ночами. Но в этом и есть кайф от жизни лично для меня — быть на острие bleeding edge и быть в первых рядах early adopters всего.
Даже вот эта статья, глядите — она о фиче, которая появится может через год, а может через два. Как только она будет работать в сколько-нибудь удобоваримом виде, я мгновенно попытаюсь заиспользовать ее где-нибудь на практике :)
Если бы я был разработчиком на всем этом хадуповом деле, в свое свободное нерабочее время я попробовал бы запустить это на JDK 11 и посомтреть, что отвалится. Потом найти соответствующие тикеты в джире (или зарепортить их, если их еще нет), и потом попроовать последовательно их исправить, пользуясь помощью разработчиков мейнлайна. Потом можно будет прийти на конференцию и рассказать об этом всем. Вполне может оказаться, что там и проблем-то не так много как кажется вначале.
OpenSource — это о том, что если не работает — пойди и сам сделай. Если нет документации к Project Loom — пойди и напиши ее сам на Хабру. Если нет описания патчей — пойди и прочитай дифф между default и fibers и оформи ее в виде статьи на хабр. Если что-то не работает на JDK 11 — пойди и переведи это на JDK 11 сам. Любая другая позиция лично для меня воспринимается как нытье :-)
>Любая другая позиция лично для меня воспринимается как нытье :-)
Ну вот у нас даже есть начальник, у которого позиция примерно такая как у вас. Я его энтузиазм даже вполне понимаю, вот только есть еще и бизнес, которому интересны его задачи. И да, можно подумать, что обычные бизнес-задачи — не интересные. Как бы не так (хотя конечно, бывают всякие)!
А перевод хадупа на java 11? Какой в этом бизнес смысл? Если он и есть — он очень сильно опосредованный. Во всяком случае для такой экосистемы, как хадуп, где и без Java найдется десятки продуктов, которые заслуживают того, чтобы обновиться на новую версию: собственно Hadoop/HDFS, Hive, Spark, HBase, Oozie, Sentry, ну и так далее по списку.
Вместе с тем, много инструментов разработки с серьёзным отставанием реагировали на обновление версии языка, и отставанию сильно помогло упомянутое выше переосмысление. Ну там было… и проблемы с производительностью, и с потреблением памяти, и даже весьма мистическое предупреждение "(Recovered) Internal inconsistency during lambda shape analysis" — всё на коде, написанном весьма даже по JLS, и вроде даже людьми сдавшими OCP-8. Сейчас-то они[инструменты] уже, может, и догнали, а только хайп ушёл на спад. В итоге вот и приходится сгонять народ с Java 8 драконовскими датами end of life.
Ну, это моё видение ситуации.
При этом OSGI делает практически все тоже самое, но на более позднем этапе — в runtime. В итоге изменения, которые требуются в сторонних модулях, сводятся как правило к нулю. Никакой перекомпиляции, пересборки и прочее вообще не нужно.
jigsaw сделана в первую очередь для разработчиков JDK. Если бы вы были разработчиком JDK, вы бы такого не написали. OSGi в контексте разработки JDK особого смысла не имеет, хотя бы потому, что несовместима с AOT-компиляцией и вообще не про то
вам как пользователю jigsaw нужен опосредованно. Благодаря нему джава не умрет в ближайшие пять лет, а просуществует еще следующие 10 лет. А там будет еще какой-нибудь большой рефакторинг, а через очередные 10 лет — еще и еще, что позволит джаве жить условно вечно
Хм. Может им еще скинуться на бедность?
Это разработчикам JDK еще нужно подтвердить, что их решения были правильны.
Что такого нового было еще в Java 9 и 10, чтобы на них вообще имело смысл переходить? Хоть что-то уровня lambda или stream из 8-ки назовете, такое чтобы must have? Грааль? Не тянет, при всей интересности. Новый GC? Тоже не тянет. Релизы раз в полгода? Так это решает их проблемы, а не наши.
Более того, даже если оракл забросит всю разработку прямо завтра — java ни при каких условиях не умрет через 5 лет, да и через 10 тоже. Просто мы «вечно» будем жить на какой-нибудь ibm j9 (которая к слову v8).
P.S. Лично я давно зарекся делать хоть какие-то прогнозы в IT на сроки больше 5 лет. Не сбывается.
Поэтому обновления на новые версии, для проектов в проме, а тем более 24*7, обычно в моей окрестности выглядят так — обновления безопасности накатываем срочно (причем с этим безопасники сами прибегают), остальные — читаем release notes и смотрим, что нас затронуло. Если ничего — то не накатываем вообще, ибо нефиг тратить свое время, и ловить возможные новые баги. Лучше уж жить со старыми, известными.
Такой режим, как вы предлагаете, наверное может себе позволить кто-то вроде гугля, у которого куча серверов, часть из которых может безболезненно отвалиться в любой момент, и на них можно протестировать все что угодно, потому что никто не заметит.
Вот и нашлась одна из причин, а дальше — главным образом, весы с контрпримерами, и вопросы о цене интегрирования.
Не вижу особого смысла.
>часть собственных проверок она имеет право превратить в «arg0->true», и под это дело немного разгрузить runtime
Не уверен. Собственные проверки — это по большей части чтение метаданных бандла, чтобы понять, какие пакеты экспортируются и импортируются. До 9 это было только в METADATA.MF. Насколько я знаю, например karaf уже поддерживает Java 9. И в моем понимании эта поддержка должна бы включать чтение данных о модулях jigsaw, и преобразование их неким образом в совместимую метаинформацию, чтобы опять же решить, что импортировать и экспортировать. Но все это все равно будет делаться при деплое бандла. Где тут может быть разгрузка, если бандлы деплоятся, стартуют, и пр. исключительно в рантайме?
В принципе, авторы декларируют работоспособность карафа под JDK 9, но что в нее входит — я не в курсе. Изначально поддержка может состоять в том, чтобы караф просто нормально стартовал под 9-кой, а поддержка бандлов, собранных 9-кой и содержащих модулей — это отдельная проблема, и я не знаю, ни решена ли она, ни планировали ли вообще ее решать.
Ну и кстати, мы вот у себя широко используем всяческий OpenSource, и при этом сидим плотно на JDK 8. По-идее, если бы среди оного попадалось что-то, собранное 9-кой, мы бы это заметили. Но что-то я ни про что такое не слышал. Что как бы намекает на популярность (а точнее, на ее отсутствие).
Ну и кстати, дискуссия в блоге котлина:
discuss.kotlinlang.org/t/kotlin-support-for-java-9-and-java-10/8054/2
что-то никто особо не рвется активно поддерживать.
Не запускайте треды — и что? Что вместо этого-то? Это единственный ныне существующий удобный примитив для написания такого рода задач. Более того, вся экосистема Java уже заточена именно под треды. Именно поэтому такое внимание уделяется разработке именно совместимого решения, а не какого угодно.
Вместо предложения "не запускайте треды" теперь появляется куда лучшее предложение — запускайте! Все сколько есть! Миллионами! Счастье всем и почти даром.
Ну точней, прямо сейчас — фича не позволяет, потому что это ранний прототип, и его не точили на высокий перфоманс. Сейчас оттачивается философия и API. Но на релизе всё будет ок.
О ресурсах все равно джуну придется думать.
Ты можешь конечно запустить 100500 легких тредов, но при этом если ты помимо чего-то простого будешь там какие-то условные интегралы считать (т.е. то, что требует какое-то время на вычисления), то на 16-ядерной машине ты сможешь запустить только 16 таких тредов, все остальные 100500 тредов, даже самые простые, тупо будут ждать, когда отпустит.
Разве не так?
По крайней мере в go и nodejs именно
Прочитал, что это. Аххахаха. Похоже, я привёл самый неудачный пример из существующих.
Понятно, почему у них там всё так хорошо.
Олег, спасибо за статью. А правильно понял что основное отличие от акторов реализованных в erlang и Scala — это возможность нормального разделения общих ресурсов?
Можете подсказать, что вы имеете ввиду когда говорите о разделении ресурсов ?
При разработке на аkka, из-за безальтернативновного выбора между тредами или тредами на jvm, все равно нужно учитывать, что процессинг сообщений не должен блокировать тред, иначе будет бобо всем остальным акторам.
Я пошел к коллегам по редакции ScalaNews и попросил прокомментировать :-) Выше ответ dos65 :) Сам я вопроса не очень понял — связь между эрлангом и скалой конечно есть, но конкретно в Java это делается просто чтобы общий ресурс в виде нативных тредов не простаивал. Чтобы сделать более общий вывод нужно хорошо знать эрланг и скалу, а я на них говнокодил недостаточно много.
За счет этого довольно легко запустить огромное количество акторов, а блокирующие нужно выносить отдельно. Файберы же по сути потоки на стеройдах, которые могут иметь общее состояние. Вопрос был об этом.
yield — это уступить дорогу, буквально. В частности такой надписью на асфальте дублируют соответствующий дорожный знак-морковку. Применительно к тредам он значит ровно тоже самое: указывает одному треду притормозить и дать проехать другому треду.
замечание абсолютно верное, что делать — непонятно. Если сейчас придумать вариант лучше, то можно его использовать в следующих статьях.
вот что у английского yield не отнимешь — оно короткое и понятное (для них). Его не стрёмно повторять. Попробуй найди слово ещё короче. А то же слово «вытесниться» — это просто капец какая длинная неповоротливая фигня, пока выговоришь — можно поесть и поспать несколько раз
О, async/await на стероидах. Сыровато, конечно.
Сейчас CompletableFuture и всякие Reactive на коне.
Akka без проблем держит миллионы "потоков". Spring MVC новый тоже подтянулся.
В общем, можно сделать троллейбус из буханки хлеба. Но зачем?.. Пусть евангелисты фигнёй страдают. Инженерам работать надо.
Что ещё важней, асинхронщину никто на самом деле не любит. Никто не любит, когда ему приносят больше проблем, если можно меньше проблем. Но в данный момент «меньше» проблем нельзя, потому что существуют конкретные бизнес-запросы на этот счёт
Когда-то реализацией такой мечты были треды. Тебе не надо разбираться, как там это всё работает в операционной системе, C++, ассемблере итп — ты просто берешь Java, фигачишь тред, и всё отлично. Ты пишешь всё в виде линейного императивного кода и можешь почти полностью игнорировать тот факт, что на самом деле никакой линейности не существует
Единственный минус тредов в том, что они слишком большие. Малая гранулярность. Ты захотел сделать какую-то мелочь, а нужно тащить целый тред. И да, можно по тредам всё вручную распихивать, но это неудобно.
И вот на помощь приходят файберы, которые снова позволяют писать обычный линейный код и притвориться, что всё выполняется строго последовательно.
Ещё интересно, что на релизе, весь тулинг тоже будет притворяться вместе с тобой. Это просто и удобно.
Что-то не понял. Берём ThreadPoolExecutor, настраиваем и начинаем давать ему Runnable в execute. Где ручное распихивание, перключение контекстов? Обмен данными, если нужен, надо будет и в файберах организовывать.
Вряд ли Main станет Fiber'ом из-за обратной несовместимости, а перевод экосистемы на Continuation опять же потребует аккуратного дробления. Но в добавок ещё и с ограничением на блокировку.
(или нет? насколько увеличится толщина методов в java.io если они будут повсеместно проверять, запущены ли они в Fiber'ах?)
И я, кстати, не согласен, что в CPU упираться лучше. Что если я не хочу в него упираться — кто мне оставит такую опцию в настройках? Хорошо настроенный пул уже будет упираться в CPU, а так это получается опять магия, как с Common FJ-pool в Stream, разве что (может быть) с меньшим количеством дедлоков. Или с большим, если не повезёт, учитывая в что в FJ не будет миллионов конкурирующих задач.
А мне кажется, что никакие проблемы с блокировками тут не решаются никак. Просто простаивающий поток, предоставленный ОС, переиспользуется другой задачей, а не консервируется до возобновления текущей. Всё. Совсем всё.
Есть третий стул. https://www.youtube.com/watch?v=dWyGM3MnN0A
Не пропаганды ради, другой точки зрения для.
Я наверное скоро выложу интервью с Венкатом (который тоже будет на Joker 2018!), он про это немножко говорил. Как написатель книжки про функциональное программирование в Java он кой чего в этом понимает)
Вот не надо обобщать на всех.
К сожалению, функциональное прогарммирование в практике Java не используется почти никак
Stream API это разве не адаптированная функциональщина? А им ой как пользуются, что даже доклад о "переиспользовании" в прошлом году был у вас.
Всё придумано до нас — это называется "кооперативная многозадачность" — https://en.wikipedia.org/wiki/Cooperative_multitasking
Разработчикам ОС проще, у них есть прямой доступ к стеку и аппаратная поддержка переключения контекстов.
Решение для написания асинхронного кода в промышленных масштабах уже придумано — Future/Promise. Конечно, это сложнее, чем синхронный код, но значичельно проще коллбэков а-ля node.js или изменяемого состояния + события а-ля Netty.
Проблем с интеграцией с синхронным кодом тоже нет — просто нужно помнить, что параллелизация синхронного кода ограничена количеством потоков в тредпуле.
Пойду-ка статью перечитаю, что ли.
Останутся маленькие заусенцы, которые могут какой-то легаси код превратить в фарш. И даже если API отработает идеально, то все равно изменится паттерн нагрузки, и в какой-то ситуации быстрее может оказаться не обязательно — лучше.
Если человек применил файберы осознанно и у него появились заусенцы — это по крайней мере ожидаемо. Если сломается то, что бинарно без изменений работало двадцать лет — это похоже на катастрофу. Для юзера это будет выглядеть дико.
Всё равно не особо понятно, и главным образом благодаря заявленной магии. Например обговаривается явное разделение мониторов по типу владельца — Fiber|Thread. А зачем конкретно делить? Нет, я в принципе-то понимаю, что выбор должен быть сознательным, но делить-то зачем?
Предположим, нечто заставляет системный примитив парковаться. Почему Fiber при этом может отдать мощности другому Continuation, а Thread, внезапно, не может? Разница такого порядка должна быть видна, разве что, на уровне достаточно глубоко системных процессов. Исключение, которое я могу придумать — это что кто-то (мир духу их) сохраняет ссылки на экземпляры Thread, дабы потом из другого Thread сравнить с другой ссылку по "==", и для Fiber нет механизмов, позволяющих вернуть тот же экземпляр ShadowThread? В чём-то другом? Какой предполагаемый механизм поломки? Если это просто «мы не знаем, но бывает всякий код», то возможно следует провести более подробное исследование узких мест, и всё-таки хакнуть сам Thread?
В итоге я, конечно, пророню скупую слезу по необходимости иметь в java.base растущее количество примитивов, делающих одно и то же, но с перламутровыми, а потом с и медными, пуговицами (ведь глупо сомневаться что ещё через N лет не придумают новые подходы ещё более эффективной параллелизации), но обратная совместимость есть фактор поддержания продаваемости, и придётся мириться.
Еще интересней, что совершенно не все фичи используются по назначению, и легко может оказаться так, что создатель программы заложился на какой-то сайд-эффект, который работает с тредами, но совершенно сломается с файберами. Какие-нибудь ситуации когда по какой-то сложнодоказуемой причине что-то успевает быстрей чего-то другого, и это обычно работает (без всякой гарантии от стандартов vm и я языка), но любой чих ломает эту логику к черту. Файберы весь такой код поломают.
Thread.currentThread указывает на непонятные постоянно меняющиеся значения
Почему это? Если он возвращает ShadowThread, то для конкретного Continuation'a должен возвращать один и тот же экземпляр, из чего-то вроде ContinuationLocal. Сюда же идут имя треда и всё подобное.
Вот что делать с ThreadLocal действительно неясно — я ведь сам уже столкнулся с ситуацией, когда мой неверно придуманный r/o кэш был помещён в ThreadLocal, из-за чего запросы разных пользователей получили возможность не читать самостоятельно из базы некоторые значения (без нарушения инкапсуляции сессии; правда, в реальности ускорения получено не было, так как контекст нового пользователя с большой вероятностью просто вытеснял из кэша старьё, и 90-95% данных таки приходится подгружать). В моём-то случае это неверное понимание, что я творил, а если кто-то на это на самом деле полагается для чего-то критичного?
Другое понимание намного опаснее, так как это как раз и есть о чём я уже говорил — расчёт на то, что некий произвольный код действительно будет находить в ThreadLocal значения, оставленные там предыдущей (никак не связанной, кроме как через внешний дизайн, не выраженный в коде) задачей, а вот этого, думаю, мы как раз и не можем строго гарантировать.
Что мешает вернутся к тем благословенным временам когда в яве небыло нативных тредов смахнуть пыль с шедулера и научить его работать не с одним нативным тредом, а с фиксированным количеством. Это снизит расходы памяти на нативные структуры.
В этих ваших файберах стек сократили с мегабайта до килобайта. Видимо за счет динамической аллокации. Если заимплементить динамическую аллокацию в тредах это сломает нативные фреймы точно так же как и в континуациях. Чинить надо так же как в континуациях :)
Нужно на каждый такой вызов заводить отдельный стек. Фокус в том что он может быть существенно меньшего размера.
Есть правда еще одна беда. Что делать если нативные вызовы блокируются?
Но тут никакие файберы не помогут и можно тупо добавлять нативных тредов в таком случае.
Двух котят с дверцами автору.
Для распределения сложной вычислительной задачи по ядрам прекрасно нативные потоки справляются.
Если же речь идёт о миллионе соединений, то можно использовать неблокирующее API. В этом случае сложность написания асинхронного кода не так критична, ибо обработчики событий не могут быть сложными (ведь их же миллионы, они не могут долго выполняться).
Непонятно сколько памяти будет выделяться под хранение локальных переменных.
Кроме того, непонятно что делать с escape анализом, где объекты для оптимизации создаются прямо в стеке вместо кучи.
Далее, континуейшен может выполниться на другом ядре, а значит надо заново заполнять кэш ядра. Напомню, что одно из преимуществ work stealing-a это локальность данных, когда отфоркнутая задача будет скорее всего выполняться на том же ядре, а значит не надо гонять данные туда-сюда.
В целом интересная абстракция. Однако непросто найти прям реальный пример практического применения. Обычно там где надо создать миллион потоков повышенные требования к ресурсам, а фибры это слишком большой оверхед.
Ситуация с parallelStream(), как мне кажется, немало народа (меня в том числе) заставила задуматься, так ли хорошо это когда любой чих может на самом деле произойти в тридевятом треде, а мне вернётся только результат.
Фиберы
Третий сервис-пак для Microsoft Windows NT 3.51 принесла в операционную систему новые сервисы под названием фиберы. Они были добавлены в Win32, чтобы облегчить портирование приложений из UNIX в WinNT. Были написаны эти однотредные серверные юниксовые приложения, которые могли иметь «доступ ко многим клиентам за раз».
Wasm.ru Треды и фиберы /27.08.2002/
Программировать с файберами не проще, чем с тредами. Файберы сильно упрощают асинхронный код, выполненный в стиле Continuation Passing (CPS), который неудобен во всем, кроме одного. Неудобен потому, что выворачивает наизнанку поток управления. И у него нет стека, из-за чего разбор всяких рекурсивных структур становится не то, чтобы совсем уже проблематичным (можно использовать явный стек), но сильно неудобным. И, что самое плохое, что метод инвазивный: весь код, который так или иначе делает ввод-вывод, должен быть написан в стиле CPS. Т.е. всё.
Файберы именно эту проблему снимают. Линейность, рекурсия, циклы, ветвления при вводе-выводе становятся именно тем, чем мы привыкли их себе представлять. Самое главное, что унаследованный код в такую среду портируется либо автоматически, либо с минорными изменениями.
Однако, при программировании с файберами появляется в явном виде передача управления планировщику, которую теперь надо продумывать. Планировщик теперь должен управлять «миллионами» файберов, что само по себе может оказаться вычислительно-емким. Да, теперь файбер не может быть остановлен в любом произвольном месте, а только на явном или неявном вводе-выводе или yield()-е. Т.е. в общем случае проблема реентерабельности объектов остается. Просто становится меньше точек реентерабельности. Как итог, файберы тоже нужно взаимно координировать, как и треды: блокировочки, семафорчики и всё такое.
Самое главное, что для чего файберы нужны — это перенос планировщика ввода-вывода из ядра OS в приложение. Т.е. приложение может иметь свой планировщик, заточенный под задачу. Интересно это только для IO-интенсивных задач, таких как нагруженные хранилища и базы данных. Потому что статистически идея файбера очень проста: поскольку ввод-вывод очень высоколатентный, то мы дробим его на отдельные мелкие волокна. И в каждый момент времени выполняется то волокно, для которого сейчас есть данные. Самый простой пример — веб-сессии. Они все независимы, низкоинтенсивны и их очень много. Тратить по треду на сессию — это очень расточительно. С диском вводом-выводом всё сложнее, но для больших RAID-массивов SSD ситуация будет точно такой же, как и с сетевым трафиком: нужно параллелить ввод-вывод.
Файбер от корутины (coroutine) отличается только API и, возможно, накладными расходами реализации. Корутины обычно явно передают управление от одной к другой, как подпрограммы. Но это не обязательно.
Файбер же — это корутина, которая реализует API треда.
Стек нативного треда — это 1 MB адресного пространства, а не физической памяти. Память под стек выделяется динамически по мере необходимости. Проблема была на 32-битных архитектурах, где адресное пространство быстро заканчивалось. На 64-битных архитектурах всё не так печально. Однако, у файбера тоже есть стек, и он тоже жрет адресное пространство. Примечание: в Project Loom они хотят пойти по какому-то особому пути, на котором собираются эту проблему обойти.
С другой стороны, большой стек — это антипаттерн. На тех задачах ввода-вывода, где возможна глубокая рекурсия (регулярные выражения, например) нужно использовать соответствующие явные структуры данных. RE2, например, или ICU4C не используют системный стек. В общем, 64K на стек — этого достаточно. 1M файберов сожрет «всего» 64G адресного пространства (не памяти!). Памяти они сожрут под стеки всего лишь 4G, что не так уж много там, где действительно нужен миллион файберов.
В общем, файберы — это хорошо и нужно. Пожелаем Рон Пресслеру удачи и скорейшего релиза!.. Его Квазар был хорош, нустр, но весьма костылен. Появятся файберы, появятся и задачи под них.
Раздача халявы: нетормозящие треды в Java. Project Loom