Как стать автором
Обновить

Комментарии 143

Это не евангелист какой-то паршивый
вентилятор на полную! :)
Я недавно променял запись в трудовой с «IT-специалиста» на «специалиста по коммуникациям», теперь штормит немного :-)

Есть предчувствие, что так очень легко нарваться на лекцию jbaruch, касающуюся введения в профессию и чистоты морального облика хаброавтора. Особенно учитывая, что сегодня интервью с программным комитетом devoops, и он там будет. Немного боязно даже.
Все лайчонки пойдут на создание нового контента. Спасибо.

Фуу, такое чувство что общаешься исключительно со школьниками средних классов. «Хардкор» в подаче для самых маленьких?)

Не предчувствуйте, с Барухом вы как бы из одной лодки и конфликта интересов быть не должно!

Ну я сам школьник средних классов — люблю потреблять именно вот такой контент. Как думаешь, что я сейчас смотрю в перерыве между работой? "Макса 100500" на фоне леопардового ковра. Сорянчик. Делал как для себя :-)

Ну я сам школьник средних классов

Надеюсь что не на полной ставке по трудовой оформлен, иначе нарушение ТК!)
Будет потом как в меме про журналиста и ученого… «Хабр окупировали школьники»

Так они его и оккупировали. Собственно, статьи про кишки OpenJDK для того и нужны, чтобы постараться повернуть колесо в положительную сторону: больше качественного контента про программирование — больше адекватных людей — которые генерят еще больше качественного контента. Каждый боец нужен и важен на фронте.

Мне тут больше экспертов и профессионалов встречается, так что спорное утверждение про аудиторию.

Про цели можно поспорить, лишь пытаюсь донести мысль что такая подача контента фокусирует ваши усилия на тех кого описали. Кто во что верит, тому и такая целевая аудитория.
Относиться плохо к школьникам — плохо.

Уровня развития школьника вполне должно хватать, чтобы мочь программировать на Java или даже C++ вполне осмысленные вещи.

И очень-очень скоро все эти школьники станут нашими коллегами, нашими начальниками, нашими товарищами.

Пусть привлекает. Если они сюда набегут — это будет праздник, обсуждение файберов пойдет куда живее
Конечно пусть процветает словоблудство) Предлагаю хаб java для «маленьких». Обращаться к аудитории «чувак» «бро». Не рекомендовать читать монографию Ахо, а исключительно посещать курсы и конференции работодателей.

Это как практикующих медиков учить по «Стоматология для чайников».
«Чувак» я уже использую (называю так почти всех людей), а вот «бро» — это отличная идея. Мои любимые стримеры на твиче так говорят. Тоже буду так делать, спасибо!
Как-бы в капиталистическом обществе живем, роялти что-ли платите за PR идею!)

А если без юмора, поскольку твои работодатели спокойно относятся к этому «прыщавому» сленгу, клянчанью лайков, мемам на каждом слайде и платят зарплату за такой маркетинг и PR. То можно сделать выводы, что ради увеличения прибыли, взяли партийный курс на развлечение и завлечение людей далеких от официальной целевой аудитории конференции — геймеров, школьников и их родителей. Запасаюсь попкорном и наблюдаю в стороне…

Хочешь сюрприз? Я на эту статью потратил свои личные выходные, и никто мне ничего за неё не заплатил. О чём, кстати, сказано в дисклеймере к статье.


У меня очень серьезные консёрны на тему, что если я буду ещё и стримить с приличной периодичностью, то учитывая работу — когда мне спать? Подготовка видосиков требует поразительно много усилий. Похоже, спать придется перестать.


Я сам геймер, вечерами постоянно играю в Overwatch (и хочу попробовать Quake Champions, а вот PUBG и батл рояли вообще не переношу) и время от времени устраиваю уютные стримы на своем Фейсбуке, вечерами после работы залипаю в Твиче, IRL тусуюсь в стримерской тусовке. Даже с летсплейщиками. Для меня именно такой формат наиболее понятен и приятен.


Поэтому когда выдалось время сделать нечто для души, а не по работе, я стал делать именно то, что стал бы смотреть сам. А теперь сорянчик, надо шлёпать — пересмотреть, чего там Дрю записал за эту пару дней.

Хочешь сюрприз? Я на эту статью потратил свои личные выходные, и никто мне ничего за неё не заплатил. О чём, кстати, сказано в дисклеймере к статье.

Респект! Не горюйте, вернется премией за KPI после сезона конференций. Материал стоящий, но подан сомнительно.

Еще есть минимум пара-тройка способов как сэкономить время на полезную и интересующую вас работу, но думаю сами догадаетесь.

По поводу остальной информации — она лишняя для меня, вместе со всем этим «сально-прыщавым» сленгом) Могу только посочувствовать вам и вашим родным по этому поводу. Но в принципе, все написанное вами подтверждает мои предположения о стратегии работодателей.

Я тоже не смог долго читать, количество вопросов подразумевает что кто-то смог.
Стиль изложения в некотором смысле вкусовщина.

а ты не завидуй. Зависть — смертный грех!
Конечно, так удобнее давить мнение джависта) Говоришь «критика=зависть» и конец дискуссии!
Ты перешел на личности в разговоре с моим коллегой. Теперь получай!
Обратитесь в профсоюз! Можете как организация завести аккаунты для родных и друзей коллеги)
Уверяю, тут нет перехода на личности. IMHO констатация фактов и фидбэк к статье.
На самом деле уже начинаешь путаться в этих fibers, asyncio, корутины, etc…
Никак не могу найти хорошего материала, когда какую технологию использовать и как.

Я правильно понимаю — если читаешь много или пишешь в сеть/файл — лучше использовать fibers/async/coroutines + пул потоков (к примеру, как делает Netty + Executors.newFixedThreadsPool()); если же обрабатываешь много данных (к примеру, эмуляция игрового мира), то лучше разбить всё по обычным потокам?

Был бы безумно рад, если б кто кинулся какой-нибудь книжкой-умной статьёй :)
Может быть, Рома elizarov Елизаров ответит :) У меня более обобщенный подход — надо изучать и пилить интересные штуки, а чего это и зачем — кому надо сам придумает применение.
У меня схожий подход, проблема лишь в том, что иногда приходится делать что-то для продакшна, и возникают вопросы по технологиям :)

Цитируя 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 говорит «я уже доделал»? Из статьи не особо понятно, чем этот подход отличается от конкретно корутин :)
Отличаются — названием? Оракл — это такая особая компания, которая даёт привычным вещам свои собственные имена. Иногда они действительно значительно более простые и запоминающиеся, чем стандартная терминология. Не всем хотелось бы трогать руками склизкий холодный зигохистоморфный препроморфизм
Мне бы понять чем файбер от корутины с точки зрения прикладного подхода отличаются :) Понятно, что это не для perfomance-dependent вычислений, но есть ли какая-то особая разница между ними, к примеру, в обработке подключений клиента? Или по-факту одно и тоже, но по разному выглядящее?
Если ты обобщенном смысле (не про названия в java и kotlin), то основная разница в наличии или отсуствии планировщика. У файбера планировщик занимается переключением контекстов, у корутины никакого планировщика нет, и этим должен заниматься ты сам в ручном режиме, в создающем-вызывающем-уничтожающем корутину коде. И корутина может быть вообще никак не связана с тредами, а быть сильно связана с вызывающим кодом. Это просто нужно для разных способов использования. Но наверное, это очень сильно вопрос терминологии и используемой технологии — сейчас придут люди и скажут, что всё я вру.
Отличие в том, что сопрограммы («корутины») обычно не имеют своего стека вызовов. Это ровно одна подпрограмма которая посреди своей работы может приостановиться. Если одна сопрограмма вызывает другую, то вызывающая сопрограмма должна выбирать будет ли она приостанавливаться при приостановке вызываемой, и если будет — это нужно еще как-то реализовать.

Волокно (fiber) же — это легковесный поток. У него есть свой стек, и приостановиться он может на любом уровне вложенности. Достоинства волокон — при поддержке стандартной библиотеки их можно сделать полностью прозрачными для программиста (неотличимыми от потоков). Недостатки волокон — без таковой поддержки они получатся половинчатыми, плюс для них нужно выделять стек (последний недостаток как раз пытаются тут устранить хитрым копированием).
Очень просто:
  • много IO, мало вычислений — lightweigh треды
  • много вычислений, мало IO — обычные треды
  • очень много вычислений — смотреть в сторону горизонтального масштабирования

Но в реальном мире простого не бывает, поэтому зависит от ситуации :)

Smalltalk, 80-e. Green Threads, Continuations «из коробки»...

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

Процессы в Smalltalk-VM суть ваши файберы сразу, иных механизмов многозадачности там нет. Компы в то время были большие, программы маленькие, и потоки — легковесные ;)

Меня вот что смущает. Идея continuations — она совсем не нова, и растет кажется из лиспа(ов), т.е. лет ей дай боже.

Если просто погуглить + java + continuations, то вы на первой же странице увидите, кроме Loom, еще парочку проектов, один из которых был сделан аж в 2007. И что-то никто особо не впечатлился. Вопрос — а почему, собственно, в этот раз должно взлететь? В чем разница-то, если в этом проекте работы осталось начать да кончить?
О каком проекте идет речь, можно ссылочку?

Сейчас в Kotlin сделали корутины и впечатлились… ну, можно сказать, все кто может использовать Kotlin. Впечатлились все. В golang есть горутины — и это одна из топовых причин, зачем вообще юзать голанг.

Что касается языка Java. Нормально без хаков в рантайме этого никак не сделать, и все кто делал — получали что-то наполовину нерабочее. В том же котлине вообще не подразумевается, что есть какой-то 20-летний легаси, который надо заставить работать без изменений и пересборки. В той же алибабе это хак виртуалки, причём прямолинейный и дорогой, и они жутко мучаясь поддерживают форки, насколько понимаю.

Здесь же это официальный проект компании Оракл, которая выделила на это лучших инженеров и бабло. Его на фуллтайм ведёт человек, который уже однажды сделал Квазар и имеет успешный опыт. Плюс поставлены вполне конкретные задачи — сделать не как попало, а сохранить главную отличительную фишку платформы Java — совместимость с legacy кодом. Все несовместимости в API, все корнер-кейсы — к этому относятся не как к мелочи, а как к важнейшим аспектам вопроса.

Плюс в целом, дозрела культура разработчиков. Пришло глобальное понимание о нужности таких штук.
rifers.org/blogs/gbevin/2005/9/23/announcing_rifecontinuations

Ну вот скажем пост от 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, это новая точка отсчёта для всех

>так что, наверное, я не самый верный человек для того, чтобы обсуждать как всё плохо, и что ваше большое начальство рассказало о том, что вы вечно будете на Java 8.

Расскажите это авторам хадупа. И не надо выдумывать всякую фигню про начальство, если вы просто не в курсе — это не зазорно, уж поверьте.
Давно портировали? Гм.

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!


Наличие открытых багов не является причиной для неиспользования.

Умением читать jira как раз и отличается практикующий программист от евангелиста :)

То что вы прислали — это не баг, это 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, ну и так далее по списку.

А вторая ссылка вообще ведет на tomee. К хадупу это никаким боком не относится, так что про версию 11 все так же непонятно, как и было.
Мигрировать с Java 8 сейчас очень больно, ведь модули — это немалое переосмысление сборки рантайма, а кроме модулей в Java 9 почти ничего и нет (вот кому надо было это «почти ничего» — те закусили пулю и перешли, у остальных «и так работает»).

Вместе с тем, много инструментов разработки с серьёзным отставанием реагировали на обновление версии языка, и отставанию сильно помогло упомянутое выше переосмысление. Ну там было… и проблемы с производительностью, и с потреблением памяти, и даже весьма мистическое предупреждение "(Recovered) Internal inconsistency during lambda shape analysis" — всё на коде, написанном весьма даже по JLS, и вроде даже людьми сдавшими OCP-8. Сейчас-то они[инструменты] уже, может, и догнали, а только хайп ушёл на спад. В итоге вот и приходится сгонять народ с Java 8 драконовскими датами end of life.

Ну, это моё видение ситуации.
Мое видение еще проще: я не занимаюсь скажем мобильной разработкой, а для серверных продуктов не видел никогда и не вижу никаких применений для jigsaw. Все случаи, когда было нужно модульность, прекрасно и давно покрыты OSGI.

При этом OSGI делает практически все тоже самое, но на более позднем этапе — в runtime. В итоге изменения, которые требуются в сторонних модулях, сводятся как правило к нулю. Никакой перекомпиляции, пересборки и прочее вообще не нужно.

jigsaw сделана в первую очередь для разработчиков JDK. Если бы вы были разработчиком JDK, вы бы такого не написали. OSGi в контексте разработки JDK особого смысла не имеет, хотя бы потому, что несовместима с AOT-компиляцией и вообще не про то


вам как пользователю jigsaw нужен опосредованно. Благодаря нему джава не умрет в ближайшие пять лет, а просуществует еще следующие 10 лет. А там будет еще какой-нибудь большой рефакторинг, а через очередные 10 лет — еще и еще, что позволит джаве жить условно вечно

>Если бы вы были разработчиком JDK, вы бы такого не написали.
Хм. Может им еще скинуться на бедность?

Это разработчикам JDK еще нужно подтвердить, что их решения были правильны.

Что такого нового было еще в Java 9 и 10, чтобы на них вообще имело смысл переходить? Хоть что-то уровня lambda или stream из 8-ки назовете, такое чтобы must have? Грааль? Не тянет, при всей интересности. Новый GC? Тоже не тянет. Релизы раз в полгода? Так это решает их проблемы, а не наши.

Более того, даже если оракл забросит всю разработку прямо завтра — java ни при каких условиях не умрет через 5 лет, да и через 10 тоже. Просто мы «вечно» будем жить на какой-нибудь ibm j9 (которая к слову v8).

P.S. Лично я давно зарекся делать хоть какие-то прогнозы в IT на сроки больше 5 лет. Не сбывается.
Новые релизы решают ваши проблемы — они чинят баги (которых напомню — двадцать тысяч только открытых), и понемножку добавляют новые фичи. Мой прогноз следующий: те кто привыкнут обновляться раз в полгода на каждую новую версию — будут в шоколаде, все остальные будут ныть, ничего не понимать, а каждый переход на новый LTS будет полным адом и светопреставлением. В результате на шестимесячные обновления перейдут все, кроме кровавых ынтерпрайзов и отчаянных садомазохистов. Не нужно задумываться, зачем мигрировать на новую версию — это просто НАДО, все уже решили за тебя.
Ну вообще-то нет. Я не помню, чтобы кто-то с багами вот так работал. Скажем, в моем личном списке багов 8-ки на сегодня ровно одна штука — падает javac на сборке одного из сторонних проектов (вроде java unrar). И это относится к сборке 144 (рекомендованной клоудерой для хадупа). Но поскольку собрать я спокойно могу сборкой 171, я это и сделал, таким образом, багов в JDK 8 для меня на сегодня не существует.

Поэтому обновления на новые версии, для проектов в проме, а тем более 24*7, обычно в моей окрестности выглядят так — обновления безопасности накатываем срочно (причем с этим безопасники сами прибегают), остальные — читаем release notes и смотрим, что нас затронуло. Если ничего — то не накатываем вообще, ибо нефиг тратить свое время, и ловить возможные новые баги. Лучше уж жить со старыми, известными.

Такой режим, как вы предлагаете, наверное может себе позволить кто-то вроде гугля, у которого куча серверов, часть из которых может безболезненно отвалиться в любой момент, и на них можно протестировать все что угодно, потому что никто не заметит.
Почему бы благородному дону не сделать OSGi поверх jigsaw? Ведь сами же и сказали — OSGi делает часть проверок позже, чем jigsaw. Следовательно, если среда OSGi может доказать, что проект построен поверх jigsaw, часть собственных проверок она имеет право превратить в «arg0->true», и под это дело немного разгрузить runtime.

Вот и нашлась одна из причин, а дальше — главным образом, весы с контрпримерами, и вопросы о цене интегрирования.
>Почему бы благородному дону не сделать OSGi поверх jigsaw?
Не вижу особого смысла.

>часть собственных проверок она имеет право превратить в «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. Но на релизе всё будет ок.
НЛО прилетело и опубликовало эту надпись здесь
Раньше нужно было запускать второй инстанс на амазоне после 1000 потоков, а сейчас — после миллиона. Хммм, как же это скажется на доходах компании, у которой огромный кусок бюджета уходит на облака, даже не знаю…
НЛО прилетело и опубликовало эту надпись здесь

О ресурсах все равно джуну придется думать.
Ты можешь конечно запустить 100500 легких тредов, но при этом если ты помимо чего-то простого будешь там какие-то условные интегралы считать (т.е. то, что требует какое-то время на вычисления), то на 16-ядерной машине ты сможешь запустить только 16 таких тредов, все остальные 100500 тредов, даже самые простые, тупо будут ждать, когда отпустит.
Разве не так?
По крайней мере в go и nodejs именно

Конечно, ядер от этого не добавится. Смысл-то в утилизации цпу (+ копеечный оверхед по памяти): 16 ядер всегда выполняют какие-то файберы. Хотя честно, не вижу разницы с обычными потоками в этом смысле, все также засыпают на локах, IO и отдают ядра другим потокам.
Разница простая — принудительного переключения нет, но само переключение очень быстрое.
Можно писать неблокирующий код, читающий из сокета по байтику, но такой же простой, как и блокирующий.
НЛО прилетело и опубликовало эту надпись здесь
EvE Online == stalkless python, нет там проблемы запустить 2000 тредов…

Прочитал, что это. Аххахаха. Похоже, я привёл самый неудачный пример из существующих.


Понятно, почему у них там всё так хорошо.

Олег, спасибо за статью. А правильно понял что основное отличие от акторов реализованных в erlang и Scala — это возможность нормального разделения общих ресурсов?

Можете подсказать, что вы имеете ввиду когда говорите о разделении ресурсов ?

Ну в каком-то смысле да, если общий ресурс тут выделяемое процессорное время на актор.
При разработке на аkka, из-за безальтернативновного выбора между тредами или тредами на jvm, все равно нужно учитывать, что процессинг сообщений не должен блокировать тред, иначе будет бобо всем остальным акторам.

Я пошел к коллегам по редакции ScalaNews и попросил прокомментировать :-) Выше ответ dos65 :) Сам я вопроса не очень понял — связь между эрлангом и скалой конечно есть, но конкретно в Java это делается просто чтобы общий ресурс в виде нативных тредов не простаивал. Чтобы сделать более общий вывод нужно хорошо знать эрланг и скалу, а я на них говнокодил недостаточно много.

По классическим работам Хевита(https://en.wikipedia.org/wiki/Carl_Hewitt) акторы не разделяют ничего общего, общение производиться за счет отсылки сообщений.
За счет этого довольно легко запустить огромное количество акторов, а блокирующие нужно выносить отдельно. Файберы же по сути потоки на стеройдах, которые могут иметь общее состояние. Вопрос был об этом.
>Ещё я иногда буду использовать слово «вытеснение» вместо английского варианта «yield». Просто слово «yield» — оно какое-то уж совсем мерзковатое. Поэтому будет «вытеснение».

yield — это уступить дорогу, буквально. В частности такой надписью на асфальте дублируют соответствующий дорожный знак-морковку. Применительно к тредам он значит ровно тоже самое: указывает одному треду притормозить и дать проехать другому треду.
по-русски то как это сказать. Я вот придумал «самовытеснение», или «вытеснение» чтобы было короче. Пошёл и самовыпилился. Если говорить «уступать», то сразу же возникают вопросы — «уступать кому», «уступать что», оно как-то ненадёжно звучит :(

замечание абсолютно верное, что делать — непонятно. Если сейчас придумать вариант лучше, то можно его использовать в следующих статьях.
Можно наверное просто «уступить дорогу» и использовать, вполне себе устоявшееся выражение, как мне кажется.
и постоянно говорить «уступить дорогу», «уступить дорогу», «уступить дорогу». Длинно. Лишние повторения. Срабатывает нюх на пахнущий код: если одно и то же повторяется несколько раз, пора отрефакторить это в отдельную функцию. В данном случае — в отдельное слово. Какое?

вот что у английского yield не отнимешь — оно короткое и понятное (для них). Его не стрёмно повторять. Попробуй найди слово ещё короче. А то же слово «вытесниться» — это просто капец какая длинная неповоротливая фигня, пока выговоришь — можно поесть и поспать несколько раз
Ну вот повезло им, что слово у них короткое, но понятное-то оно потому, что является отсылкой к дорожному движению.
А чем «отдать/уступить [управление]» не подходит?

О, async/await на стероидах. Сыровато, конечно.


Сейчас CompletableFuture и всякие Reactive на коне.
Akka без проблем держит миллионы "потоков". Spring MVC новый тоже подтянулся.


В общем, можно сделать троллейбус из буханки хлеба. Но зачем?.. Пусть евангелисты фигнёй страдают. Инженерам работать надо.

Там же в самом верху картинка была с двумя стульями. Если коротко, то асинхронный код (даже если он спрятан за сахаром) — очень сложный для чтения, очень сложный даже для написания, у него очень неприятная отладка и инструменты для нее плохие — короче, дорогой в разработке и поддержке.

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

Когда-то реализацией такой мечты были треды. Тебе не надо разбираться, как там это всё работает в операционной системе, C++, ассемблере итп — ты просто берешь Java, фигачишь тред, и всё отлично. Ты пишешь всё в виде линейного императивного кода и можешь почти полностью игнорировать тот факт, что на самом деле никакой линейности не существует

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

И вот на помощь приходят файберы, которые снова позволяют писать обычный линейный код и притвориться, что всё выполняется строго последовательно.

Ещё интересно, что на релизе, весь тулинг тоже будет притворяться вместе с тобой. Это просто и удобно.
Почему это «вручную распихивать по потокам»? А тред пул экзекьютеры разве не эту задачу выполняют?
тредпул экзекьюторы решают задачу запуска — задачу приостановки они не решают. Нужно писать это руками. А тут предполагается, что все это будет уже за тебя сделано разработчиками Лума, и оно будет иметь универсальный интерфейс, а не твои мегакостыли
Это и есть распихивать вручную. Приходится руками обеспечивать свое собственное переключение контекстов и обмен данных между задачами.

Что-то не понял. Берём ThreadPoolExecutor, настраиваем и начинаем давать ему Runnable в execute. Где ручное распихивание, перключение контекстов? Обмен данными, если нужен, надо будет и в файберах организовывать.

Для этого, во-первых, нужно сначала аккуратно побить задачи на Runnable, во-вторых, что-то сделать с блокирующими вызовами. Большинство задач выглядят как прочитать немножко данных, возможно, из разных источников, что-то с ними сделать и куда-то записать результаты, возможно, в несколько мест. В случае сегодняшнего Executor API на Thread'ах нельзя сделать это одновременно с перформансом асинхронного API (при котором придется обеспечивать обмен данными, зачастую весьма нетривиально) и с удобством синхронного API.
Но то же самое нужно будет делать и для Fiber'ов.
Вряд ли Main станет Fiber'ом из-за обратной несовместимости, а перевод экосистемы на Continuation опять же потребует аккуратного дробления. Но в добавок ещё и с ограничением на блокировку.
(или нет? насколько увеличится толщина методов в java.io если они будут повсеместно проверять, запущены ли они в Fiber'ах?)
Блокирование на большинстве IO-операций и reentrant lock'ах будут «отдавать» текущий тред на корм другим Fiber'ам. Даже уже написанный код. И да, Main не станет Fiber'ом. Однако запустить Fiber на ForkJoinPool'е так же просто, как и запустить Runnable. При этом его не потребуется аккратно разбивать на части — внутри может выполнятся «как бы последовательный» код, в том числе легаси, в том числе уже скомпилированный до нас. Т.е. запускаем миллион Fiber'ов (вместо Runnable) и они перестают блокировать друг друга ожиданиями IO и прочими lock'ами. Упираемся дальше фактически в CPU, что много лучше, чем упираться в конфигурацию ThreadPool'а.
Но постойте? Если блокирование на io всё равно отдаёт ресурсы файберам, для чего нужно было городить разделение Thread|Fiber? Ведь это фактически уже значит, что любой тред становится, эффективно говоря, своеобразным файбером уже благодаря этому факту. Я тут уже в нескольких ветках пытаюсь этот на этот вопрос найти ответ.

И я, кстати, не согласен, что в CPU упираться лучше. Что если я не хочу в него упираться — кто мне оставит такую опцию в настройках? Хорошо настроенный пул уже будет упираться в CPU, а так это получается опять магия, как с Common FJ-pool в Stream, разве что (может быть) с меньшим количеством дедлоков. Или с большим, если не повезёт, учитывая в что в FJ не будет миллионов конкурирующих задач.
Как я понял, блокирование на io всё равно отдаёт файберам только если сейчас выполняется другой файбер.

А мне кажется, что никакие проблемы с блокировками тут не решаются никак. Просто простаивающий поток, предоставленный ОС, переиспользуется другой задачей, а не консервируется до возобновления текущей. Всё. Совсем всё.

Да, я тоже это примерно так и понимаю сейчас. Но если мне не изменяет память, то ожидалось что это так и будет когда-нибудь работать чуть ли не с самого начала, потому и сделан был Thread::yield. По-прежнему неясно, как введение отдельных классов поможет (разве что эти классы нужны только на этапе прототипа, и потом максимально сольются с Thread).
Оу, надобно глянуть, спасибо!

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

Асинхронный код не сложен для чтения если используется функциональное программирование. Просто люди из последних сил цепляются за динозавра\ не хотят учить новое.
К сожалению, функциональное прогарммирование в практике Java не используется почти никак. В своей массе, у большинства разработчиков. Ну и да, язык-то у нас ни разу не Haskell, он не шибко помогает писать чистый код, архитектуру портов-адаптеров с кругом чистоты, и вот это все. Даже в F# есть полу нерешаемые проблемы!

Я наверное скоро выложу интервью с Венкатом (который тоже будет на Joker 2018!), он про это немножко говорил. Как написатель книжки про функциональное программирование в Java он кой чего в этом понимает)
>К сожалению, функциональное прогарммирование в практике Java не используется почти никак.

Вот не надо обобщать на всех.
Ну оно и понятно, ведь Java изначально ООП язык, да еще с многолетним багажем. А вот почему народ с нее не хочет переходить на Scala мне остается непонятным. И это при том, переход плавный и экосистема та же — не то что Haskell учить.

К сожалению, функциональное прогарммирование в практике Java не используется почти никак

Stream API это разве не адаптированная функциональщина? А им ой как пользуются, что даже доклад о "переиспользовании" в прошлом году был у вас.

Как вы в стримах на момент компиляции сможете обеспечить, чтобы все используемые в стримах функции были чистыми, а все данные — немутабельными?
Есть ощущение, что многие люди забывают о том, что функциональщина — это про чистоту и иммутабельность, а не про лямбды и чейны.

Всё придумано до нас — это называется "кооперативная многозадачность" — https://en.wikipedia.org/wiki/Cooperative_multitasking


Разработчикам ОС проще, у них есть прямой доступ к стеку и аппаратная поддержка переключения контекстов.

Да, я где-то там в дебрях статьи ссылаюсь на эту статью :) Но вопрос не в кооперативной многозадачности как таковой, а в том, как бы её так впилить во вполне конкретную Hotspot JVM, чтобы никто не пострадал (в особенности легаси код).

Решение для написания асинхронного кода в промышленных масштабах уже придумано — Future/Promise. Конечно, это сложнее, чем синхронный код, но значичельно проще коллбэков а-ля node.js или изменяемого состояния + события а-ля Netty.


Проблем с интеграцией с синхронным кодом тоже нет — просто нужно помнить, что параллелизация синхронного кода ограничена количеством потоков в тредпуле.

Здесь не решается задача написания асинхронного кода. Тут решается прямо противоположное — из предположения что мы пишем нормальный линейный код, как сделать, чтобы он не тормозил. Дальше замечаем, что код обычно тратит треды на всевозможное IO и прочие блокировки (для огромной части аудитории их задачи IO-bound, или даже database-bound, например для ынтерпрайзных веб-разработчиков). Поэтому идея в том, чтобы код не жрал треды в то время, когда ждет ту же базу данных. И дальше все это — просто генерализация этой мысли на более общие конструкции в масштабах всей виртуальной машины в целом. В частности, поддержку этой фичи магическим образом получит легаси код, который висит на все том же файловом апи из ждк, в которую и впиливается поддержка файберов под капотом.
Но если «получит магическим образом», то почему нужен класс Fiber? Чем провинился Thread? Метаданными?
Пойду-ка статью перечитаю, что ли.
Потому что полной совместимости, скорей всего, достичь не получится. Файбер похож на тред, но это во многом не тред, и совместимость там должна работать только в том смысле, что если легаси код запустить в файбере, то он скорей всего не поломается.

Останутся маленькие заусенцы, которые могут какой-то легаси код превратить в фарш. И даже если API отработает идеально, то все равно изменится паттерн нагрузки, и в какой-то ситуации быстрее может оказаться не обязательно — лучше.

Если человек применил файберы осознанно и у него появились заусенцы — это по крайней мере ожидаемо. Если сломается то, что бинарно без изменений работало двадцать лет — это похоже на катастрофу. Для юзера это будет выглядеть дико.
ThreadLocal'ы почти наверняка сломаются. Ведь невозможно узнать, для какой именно цели они были использованы: то ли какая-нибудь хитрая оптимизация, то ли «защита» от конкурентного доступа, то ли вообще что-то в голову ударило из разряда «а не запилить ли мне тут ThreadLocal? круто же будет».
[Перечитал(правда, по диагонали)]
Всё равно не особо понятно, и главным образом благодаря заявленной магии. Например обговаривается явное разделение мониторов по типу владельца — Fiber|Thread. А зачем конкретно делить? Нет, я в принципе-то понимаю, что выбор должен быть сознательным, но делить-то зачем?

Предположим, нечто заставляет системный примитив парковаться. Почему Fiber при этом может отдать мощности другому Continuation, а Thread, внезапно, не может? Разница такого порядка должна быть видна, разве что, на уровне достаточно глубоко системных процессов. Исключение, которое я могу придумать — это что кто-то (мир духу их) сохраняет ссылки на экземпляры Thread, дабы потом из другого Thread сравнить с другой ссылку по "==", и для Fiber нет механизмов, позволяющих вернуть тот же экземпляр ShadowThread? В чём-то другом? Какой предполагаемый механизм поломки? Если это просто «мы не знаем, но бывает всякий код», то возможно следует провести более подробное исследование узких мест, и всё-таки хакнуть сам Thread?

В итоге я, конечно, пророню скупую слезу по необходимости иметь в java.base растущее количество примитивов, делающих одно и то же, но с перламутровыми, а потом с и медными, пуговицами (ведь глупо сомневаться что ещё через N лет не придумают новые подходы ещё более эффективной параллелизации), но обратная совместимость есть фактор поддержания продаваемости, и придётся мириться.
Ну так уже не всё Thread API работает. Не работает stop, suspend, resume — и вряд ли начнут. Непонятно что делать с ThreadLocal. Thread.currentThread указывает на непонятные постоянно меняющиеся значения. Непонятно что делать с нативным кодом, синхронизованными блоками, wait/notify, и еще кучей вещей. Пресслер говорит, что вот именно это они сейчас стараются как-то починить хотя бы на уровне философии. Вот в Котлине это на уровне философии починено так: а вы не юзайте просто currentThread() или будьте готовы к этому поведению. Но легаси код на Java к нему не готов.

Еще интересней, что совершенно не все фичи используются по назначению, и легко может оказаться так, что создатель программы заложился на какой-то сайд-эффект, который работает с тредами, но совершенно сломается с файберами. Какие-нибудь ситуации когда по какой-то сложнодоказуемой причине что-то успевает быстрей чего-то другого, и это обычно работает (без всякой гарантии от стандартов vm и я языка), но любой чих ломает эту логику к черту. Файберы весь такой код поломают.
Thread.currentThread указывает на непонятные постоянно меняющиеся значения

Почему это? Если он возвращает ShadowThread, то для конкретного Continuation'a должен возвращать один и тот же экземпляр, из чего-то вроде ContinuationLocal. Сюда же идут имя треда и всё подобное.


Вот что делать с ThreadLocal действительно неясно — я ведь сам уже столкнулся с ситуацией, когда мой неверно придуманный r/o кэш был помещён в ThreadLocal, из-за чего запросы разных пользователей получили возможность не читать самостоятельно из базы некоторые значения (без нарушения инкапсуляции сессии; правда, в реальности ускорения получено не было, так как контекст нового пользователя с большой вероятностью просто вытеснял из кэша старьё, и 90-95% данных таки приходится подгружать). В моём-то случае это неверное понимание, что я творил, а если кто-то на это на самом деле полагается для чего-то критичного?

Нельзя бездумно возвращать тот же самый shadow thread в currentThread. Можно поломать какой-нибудь хитрый happens-before в чужой логике оптимизаций, где будет currentThread == previousThread -> optimized branch; else -> common branch.
Достаточно потребовать чтобы засыпание Continuation было happens-before его пробуждения, и подобная поломка станет невозможной.
Действительно, как-то не подумал. Конечно, еще останется проблема с нативным кодом, использующем понимание Java Thread = OS Thread. Ну и в целом, в неведомом коде может быть куча логики вокруг currentThread, какие-нибудь свои велосипедные ThreadLocal'ы.
Велосипедных ThreadLocal'ов как раз пожалуй опасаться не нужно, если экземпляр ShadowThread всё же будет тот же самый.
Другое понимание намного опаснее, так как это как раз и есть о чём я уже говорил — расчёт на то, что некий произвольный код действительно будет находить в ThreadLocal значения, оставленные там предыдущей (никак не связанной, кроме как через внешний дизайн, не выраженный в коде) задачей, а вот этого, думаю, мы как раз и не можем строго гарантировать.
Я конечно извиняюсь, но почему бы просто не починить имеющиеся треды вместо создания новой фичи?

Что мешает вернутся к тем благословенным временам когда в яве небыло нативных тредов смахнуть пыль с шедулера и научить его работать не с одним нативным тредом, а с фиксированным количеством. Это снизит расходы памяти на нативные структуры.

В этих ваших файберах стек сократили с мегабайта до килобайта. Видимо за счет динамической аллокации. Если заимплементить динамическую аллокацию в тредах это сломает нативные фреймы точно так же как и в континуациях. Чинить надо так же как в континуациях :)
Кстати есть довольно простое решение проблемы с нативными вызовами.

Нужно на каждый такой вызов заводить отдельный стек. Фокус в том что он может быть существенно меньшего размера.

Есть правда еще одна беда. Что делать если нативные вызовы блокируются?
Но тут никакие файберы не помогут и можно тупо добавлять нативных тредов в таком случае.
А что если Java код с ожиданием был вызван из нативного? We need to go deeper.jpg
Не вижу проблемы. Просто продолжаем использовать Java стек с того места из которого вызвали нативный метод. Для ясности вставить dummy фрейм с пометкой «если вы вернулись сюда, то на самом деле вам нужно вернутся в нативный код».
Нативный код может не ожидать переноса стека по памяти.
Так потому и предлагается заводить под него отдельный стек, который не будет нуждаться в переносе.
А его и не надо переносить. Его специально в отдельном месте хранить надо и запинивать при использовании.
Не пишу и, надеюсь, никогда не буду писать на джаве, но подача настолько великолепна, что прочитал целиком.
Двух котят с дверцами автору.
Спасибо! Цель в том, чтобы в хабе Java всегда было что почитать из научно-популярного. Оно все будет про джаву в целом, но можно и просто так повтыкать. Еще что-то подобное будет про .NET, если я на него время найду
Интересно, а если реальная необходимость в создании миллиона фибров?
Для распределения сложной вычислительной задачи по ядрам прекрасно нативные потоки справляются.

Если же речь идёт о миллионе соединений, то можно использовать неблокирующее API. В этом случае сложность написания асинхронного кода не так критична, ибо обработчики событий не могут быть сложными (ведь их же миллионы, они не могут долго выполняться).
Это для того, чтобы люди могли фигачить файберы каждый раз, когда им хочется. Чтобы не нужно было трястись за каждую копейку, ой а имею ли я право тут потратить столько ресурсов и сделать тред. Надо — делай! Хоть каждую строчку в файбер зворачивай, с чистой душой и совестью.
А что если человек сделает файбер с огромными вычислениями? Как я понимаю, основной смысл файберов, это чтобы их приостонавливали (и желательно почаще), а если кто-то шибко умный запустит while(true); то все точно также сломается
Он единолично захватит на себя тред, да. Но даже если у тебя жесткосвязанный цикл без вызова внешних функций, ты как автор этого цикла наверняка сможешь руками вызвать yield когда надо, типа каждый десятый проход. Или даже — каждый первый, а планировщик уже сам разберется, стоит ли пользоваться этим yield-ом или дать тебе выполниться дальше. У того же golang совершенно точно такие же ограничения на сильносвязанный код, но гошники прям кипятком писают от того, какие горутины хорошие.
А уже есть публичное апи для yield? Или пока в мечтах?
Ну там есть функция yield без параметров) «Публичного» там нет ничего, это ранний прототип, который изменяется со скоростью света.
Удобно, хотя с другой стороны, с разбегу не смог придумать use-case.
Файберы делают поведение программы менее предсказуемым.
Непонятно сколько памяти будет выделяться под хранение локальных переменных.
Кроме того, непонятно что делать с escape анализом, где объекты для оптимизации создаются прямо в стеке вместо кучи.

Далее, континуейшен может выполниться на другом ядре, а значит надо заново заполнять кэш ядра. Напомню, что одно из преимуществ work stealing-a это локальность данных, когда отфоркнутая задача будет скорее всего выполняться на том же ядре, а значит не надо гонять данные туда-сюда.

В целом интересная абстракция. Однако непросто найти прям реальный пример практического применения. Обычно там где надо создать миллион потоков повышенные требования к ресурсам, а фибры это слишком большой оверхед.

Непонятно с точки зрения разработчика технологии файберов или пользователя-прикладника? Пользователю то что — он просто фигачит файберы и в ус не дует.
если следовать вашей логике то пользователь точно также может фигачить потоки и в ус не дуть
Не может. Во-первых, через десять тысяч потоков все начнет тормозить (особенно в шиндовсе). Во-вторых (если вы внимательно читали статью), один поток занимает примерно 1 мегабайт памяти, и миллион потоков (даже если б они не тормозили) занял бы терабайт оперативки. У вас есть терабайт оперативки? Пусть даже на проде, а не на личном ноутбуке?
Тем не менее, в большинстве случаев, средневзятому пользователю пары тысяч потоков вполне хватит. (нисколько не хочу умалять потребность в кооперативной многозадачности)
Сейас к потокам относятся как к некой священной корове. Их считают, их вызывают аккуратно, над ними думают. Существует вообще такая идея как «тредов хватит или не хватит». Наличие файберов позволит заворачивать в файбер чуть ли не каждую строчку :-) Кто знает, сколько при этом файберов наплодится?

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

Ну все-таки каждая строчка перебор, кажется, что переключение контекстов файберов хоть и дешевле тредов, но не бесплатно. Думать головой, к сожалению, все еще придется.
Это наверное оффтоп, но мне кажется что есть вполне насущная проблема: если сейчас наслушаться Шипилева и начать говнокодить многопоточно, то как нефиг делать можно получить программу, которая будет *медленней* чем последовательная версия, ну потому что ты просто не понимаешь что творишь. И вот файберы могут помочь тем людям, кто уже готовы к написанию более интересного кода, но еще не готовы к тому чтобы удалиться в высокие горы и медетировать в пещере над тонкостями джава мемори модели. Желания испоганить что-то будет меньше, если все и так работает.
Кажется, совсем не обязательно наслушиваться Шипилева, чтобы начать говнокодить сразу в несколько потоков. И как раз эта категория разработчиков вполне может сделать медленнее на файберах, чем просто линейно. Но да, быстрее, чем на тредах)
На шиндовс вы очевидно наговариваете попусту.
Когда в комментарии встречается слово «очевидно» в не юмористическом контексте, это обычно значит, что у кого-то не хватило аргументов чтобы потвердить свое мнение, поэтому аргументы заменены на «очевидно»
Те самые фиберы?

Фиберы

Третий сервис-пак для Microsoft Windows NT 3.51 принесла в операционную систему новые сервисы под названием фиберы. Они были добавлены в Win32, чтобы облегчить портирование приложений из UNIX в WinNT. Были написаны эти однотредные серверные юниксовые приложения, которые могли иметь «доступ ко многим клиентам за раз».
Решил таки оставить свои 2 копейки по такой животрепещущей теме.

Программировать с файберами не проще, чем с тредами. Файберы сильно упрощают асинхронный код, выполненный в стиле Continuation Passing (CPS), который неудобен во всем, кроме одного. Неудобен потому, что выворачивает наизнанку поток управления. И у него нет стека, из-за чего разбор всяких рекурсивных структур становится не то, чтобы совсем уже проблематичным (можно использовать явный стек), но сильно неудобным. И, что самое плохое, что метод инвазивный: весь код, который так или иначе делает ввод-вывод, должен быть написан в стиле CPS. Т.е. всё.

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

Однако, при программировании с файберами появляется в явном виде передача управления планировщику, которую теперь надо продумывать. Планировщик теперь должен управлять «миллионами» файберов, что само по себе может оказаться вычислительно-емким. Да, теперь файбер не может быть остановлен в любом произвольном месте, а только на явном или неявном вводе-выводе или yield()-е. Т.е. в общем случае проблема реентерабельности объектов остается. Просто становится меньше точек реентерабельности. Как итог, файберы тоже нужно взаимно координировать, как и треды: блокировочки, семафорчики и всё такое.

Самое главное, что для чего файберы нужны — это перенос планировщика ввода-вывода из ядра OS в приложение. Т.е. приложение может иметь свой планировщик, заточенный под задачу. Интересно это только для IO-интенсивных задач, таких как нагруженные хранилища и базы данных. Потому что статистически идея файбера очень проста: поскольку ввод-вывод очень высоколатентный, то мы дробим его на отдельные мелкие волокна. И в каждый момент времени выполняется то волокно, для которого сейчас есть данные. Самый простой пример — веб-сессии. Они все независимы, низкоинтенсивны и их очень много. Тратить по треду на сессию — это очень расточительно. С диском вводом-выводом всё сложнее, но для больших RAID-массивов SSD ситуация будет точно такой же, как и с сетевым трафиком: нужно параллелить ввод-вывод.

Файбер от корутины (coroutine) отличается только API и, возможно, накладными расходами реализации. Корутины обычно явно передают управление от одной к другой, как подпрограммы. Но это не обязательно.
Файбер же — это корутина, которая реализует API треда.

Стек нативного треда — это 1 MB адресного пространства, а не физической памяти. Память под стек выделяется динамически по мере необходимости. Проблема была на 32-битных архитектурах, где адресное пространство быстро заканчивалось. На 64-битных архитектурах всё не так печально. Однако, у файбера тоже есть стек, и он тоже жрет адресное пространство. Примечание: в Project Loom они хотят пойти по какому-то особому пути, на котором собираются эту проблему обойти.

С другой стороны, большой стек — это антипаттерн. На тех задачах ввода-вывода, где возможна глубокая рекурсия (регулярные выражения, например) нужно использовать соответствующие явные структуры данных. RE2, например, или ICU4C не используют системный стек. В общем, 64K на стек — этого достаточно. 1M файберов сожрет «всего» 64G адресного пространства (не памяти!). Памяти они сожрут под стеки всего лишь 4G, что не так уж много там, где действительно нужен миллион файберов.

В общем, файберы — это хорошо и нужно. Пожелаем Рон Пресслеру удачи и скорейшего релиза!.. Его Квазар был хорош, нустр, но весьма костылен. Появятся файберы, появятся и задачи под них.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий