С Алексеем мы подробно поговорили:
- про грядущие изменения в классе String;
- про то, кто же на самом деле разрабатывает OpenSource;
- про системных разработчиков и их карьеру;
- про обмен технологиями, «научную» и «продуктовую» разработку;
- про сложность низкоуровневых задач;
- про развитие Java-сообщества и бенчмарк-войны;
- про mutable vs immutable;
- про Unsafe;
- про JMH, бенчмарки и узкую специализацию.
Вот видео нашего разговора. Больше часа длиной, можно слушать в дороге.
Ниже под катом — расшифровка нашей беседы для тех, кто видео не очень.
Про изменения в String
— Алексей, ты раньше очень много рассказывал про Performance, а в последнее время много занимаешься классом String. Расскажи, пожалуйста, с чем это связано?
— Про String я тоже рассказываю с точки зрения Performance, поскольку участвую в проектах, которые направлены на оптимизацию строк. В этой области ежедневно делается много мелких оптимизаций, но мы делаем два крупных изменения.
Первое — это Сompact Strings. Символы большой части cтрингов, которые есть в Java-приложениях, помещаются чуть ли не в ASCII. Это означает, что на каждый символ в String можно потратить 1 байт, а не 2, как этого требует спецификация char. Сегодня внутри String, у внутренний storage – это массив char. Он сильно оптимизирован, и люди ожидают от него высокой производительности. Поэтому, для того чтобы попытаться сжать эти строки, нужно сделать два представления этого String: одно представление — типичное, char array, а второе — byte array, в котором каждый байт соответствует конкретному символу. И там нужно много перформансной работы, которая обеспечит, как у нас написано в релиз-критериях, «non-regression». Чтобы пользователи, которые переключатся с Java 8 на Java 9, не только не испытали боль, а испытали счастье и performance boost от этой нашей фичи.
И там много разных движущихся штук, о том, как «библиотека» работает, как и что делается с конкатенацией стрингов, как рантайм обрабатывает всю эту штуку. В общем, там много мелких деталей.
— А не стремно вообще? Класс String — он же через всю JDK насквозь проходит
— Стремно! На деле можно даже увидеть, что под оригинальным предложением от парней из Class Library Team, есть несколько забавных комментариев. Один — от Мартина Буххольца (Martin Buchholz) из Google, который известен тем, что он один из майнтейнеров JSR-166. Мартин в свое время сказал что-то типа «это сложная задача, удачи!». Второй комментарий — от меня, что-то в духе: «Ну, я, ребят, не верю, что это можно сделать, потому что черт его знает… String — такой класс. Его реально опасно трогать».
Сейчас мы потратили полгода на аккуратное прототипирование этого изменения, аккуратные измерения, выработку понимания, как это все влияет на перформанс, на выбор правильной стратегии кодогенерации… И сейчас я довольно счастлив, потому что я понимаю, что это изменение, которое казалось опасным, стало понятным после всей этой работы. Знание всех плюсов и минусов помогает, и с ним все вполне нормально.
— А что теперь будет с теми, кто для ускорения перформанса своего кода нагло лез в char array, который лежит в стринге?
— Их ждет сюрприз. По спецификации никто не гарантирует, что внутри строки лежит char-массив. Я думаю, что люди, которые лезут в кишки для того, чтобы выиграть какой-то перформанс, уже изначально подписываются на то, что они должны следить за всеми изменениями.
— А что такое «no performance regression»? Есть какой-то набор тестов, есть какие-то критерии его оценки?
— Есть формальное и неформальное отношение к этому. Неформальное отношение состоит в том, что у нас есть большое сообщество, которое привыкло к тому, что мажорный релиз работает как минимум не медленнее, чем прошлый мажорный релиз. Потому что иначе возникают проблемы, как мигрировать на новую версию. Поэтому, когда ты разрабатываешь новую фичу, ты помнишь, что не можешь просто так провалить перформанс, нужно обязательно где-то выиграть.
И есть формальные критерии, которые говорят о том, можно просадить перформанс на столько-то процентов на таких-то ворклоадах. Но это внутренние дела команды разработчиков, а не OpenJDK. Скорее отношение именно такое — мы понимаем, что сообщество хочет, чтобы Java не регрессировала. Мы тоже хотим, чтобы Java не регрессировала. На этом невысказанном предположении и держится наша разработка.
— А вы как-то общаетесь с большими вендорами, с производителями энтерпрайзных серверов, у которых строки на строках и строками погоняют?
— Все довольно просто. Мы работаем в большой корпорации, у нас куча внутренних заказчиков. И их вполне достаточно. Это только кажется, что опенсорс подвешен в воздухе, что разрабатывается сам по себе, хакерами-энтузиастами…
Обычно все наоборот. Есть крупные игроки, которые финансируют разработку по каким-то своим внутренним причинам. Почему Oracle купил Java у Sun и начал вкладывать в ее развитие?
Дело в том, что когда ты вкладываешься в платформу, ты своей разработческой организации даешь большие бонусы. Если у тебя есть продукт, в котором есть перформансная проблема, и ты знаешь, что она локализована в рантайме, ты можешь прийти к своим разработчикам и сказать: «Ребята, вот вам баг! А ну-ка быстренько чините». И разработчики понимают, что им за это платят зарплату и идут чинить.
Про системных разработчиков и их карьеру
— Ты человек суперизвестный. Наверняка, тебе каждый день пишут в LinkedIn куча хедхантеров и пытаются тебя перекупить. Почему ты до сих пор в Oracle?
— Ты знаешь, я давно пытаюсь ответить себе на этот вопрос и постоянно отвечаю другим. Я в блоге или в какой-то книжке прочитал, что если посмотреть на то, как слои продуктов расположены в нашей индустрии, то мы видим, что есть железо, есть операционные системы, библиотеки, приложения и т.д. И если посмотреть на популяцию разработчиков в этих всех слоях, то получается перевернутая пирамида.
Внизу люди, которые занимаются низкоуровневым фундаментом. И этих людей очень мало. По объективным причинам — туда достаточно высокий порог вхождения, нужны большой опыт и хорошее образование для того, чтобы ты смог там что-то делать разумное.
— Иными словами, чтобы улучшить интеловский процессор, нужно...
— Нужно долго и много учиться. Гораздо больше, чем, например, для того, чтобы написать Android-приложение. Для того, чтобы стать хорошим системщиком, нужно 5–10 лет индустриального опыта. Когда ты уже набрался этого опыта, кажется, что твое место в этой экосистеме как раз на этом низком уровне. Перейти из этого уровня и писать какие-то приложения энтерпрайзные можно, конечно, но это означает, что ты подставляешь всех тех людей, которые рядом с тобой вот там внизу копаются в этом всем. Там внизу существенный дефицит кадров. Там столько работы — просто тьма. Я более-менее трезво пытаюсь оценить соотношение работы, которую мы можем делать и той, которая нужна. И это соотношение один к 10, а то и к 100.
— То есть людей очень не хватает?
— Да, и это не особенность Java. Это особенность этого системного уровня. Там мало людей, много работы, поэтому там хорошие интересные задачки. Это дает возможность выбирать, какими задачами ты хочешь заниматься. Из 100 задач, которые у тебя есть ты можешь выбрать задачи, которые дают:
- а) профит комьюнити;
- б) профит твоей компании;
- в) профит тебе лично.
— Вообще это очень интересный вопрос – вопрос денег. Обычно чем меньше людей, тем они дороже стоят. У меня же ощущение, что в нашей индустрии как-то все это по-другому устроено. Так?
— Нет, системщики стоят как раз дорого. Хорошие системщики стоят очень дорого. И самое главное, что там предложение существенно меньше чем спрос. И существенно меньше конкуренции. Нет такого, что я сижу у себя в гараже и пилю свой стартап, молясь, чтобы кто-нибудь в соседнем гараже не придумал ровно такую же идею стартапа и не вышел с ней…
В моей области всех людей, которые занимаются чем-то похожим на мое дело, можно перечесть в одном письме. И никакой особенной конкуренции нет. Поэтому, скажем, веселые отраслевые конференции типа того же JVMLS, — это забавное зрелище.
Когда ты читаешь какой-нибудь форум программистский, там, например тяжба — «какой язык лучше?», «какая платформа лучше?» и т.д. А когда ты находишься в компании JVMLS, когда рядом сидят люди, которые реально работают на «нижнем уровне», там царит согласие и взаимопонимание. Потому что там все в одной лодке, все дико перегружены, у всех похожие проблемы…
Это такая большая психотерапевтическая сессия. Там нет «битья пяткой в грудь», нет утверждений, что «мы сделали лучше, а вы все полный отстой». Там, натурально, понимание и братство по модулю каких-то личных симпатий и антипатий.
— А где современному студенту или недавнему выпускнику научиться системному программированию? У меня ощущение, что в современных ВУЗах преподают по учебникам и лекалам 80-х годов.
— И это не очень плохо, потому что фундаментальная наука остается фундаментальной. И не зависит от конъюнктуры рынка. Есть классические книжки, учебники, которые стали классическими в программах ВУЗов. Может быть не в советских и не российских ВУЗах. Можно просто взять программу какого-нибудь Стэнфорда или MIT, и посмотреть, что им читают, по каким учебникам им это читают.
— Например, Computer Science 101?
— Computer Science 101 — это обычный вводный курс. А есть специализированные курсы и к ним учебники-текстбуки. Если нет возможности посмотреть в онлайне какой-то курс, можно найти просто текстбук, который обычно является классическим трудом. И прямо по нему учиться. Я в России знаю довольно мало школ, которые это делают. В Новосибирске, например, была в свое время школа, которую академик Ершов еще делал, школа компиляторщиков.
— Это имеет отношение к Excelsior в современном виде?
— Excelsior, я думаю, родился там именно потому, что были люди с достаточной экспертизой. Они могли скучковаться и делать подобного рода продукты…
А если после учебников хочется практики, то в большинстве компаний, которые занимаются подобного рода программированием, есть открытые позиции интернов и джуниоров. Можно на практике пощупать, чем отличается то, что написано в текстбуке от того, что происходит в реальности.
— С тобой так же примерно происходило?
— Да. Будучи студентом, я попал интерном в команду Intel, которая занималась Java-рантаймами. С одной стороны, я учился в универе и читал как раз книжки какого-нибудь Мучника, Хеннесси-Паттерсона, Таненбаума и прочих, а с другой стороны — у меня на работе был настоящий продукт, в который можно было попробовать перенести идею из учебника. Или просто читать проект и понимать, что вот то, о чем ты читал два месяца назад в учебнике. Такая вот теория и практика.
Это похоже на то, что называется «система Физтеха»: когда студентам первые три курса дают фундаментальные основы (математику, физику, computer science), а потом их направляют на условно-базовые кафедры в научных институтах, промышленных производствах, где они под крылом практикующего руководителя делают настоящую научную работу.
У нас в индустрии эффективный инструмент примерно такой же — студенту нужно получить базу в ВУЗе, а потом влиться в какую-нибудь организацию, в которой начать свои знания использовать на практике. Яндекс, ABBYY, Сбертех и прочие компании, насколько я понимаю, двигаются именно в том же самом направлении. Они хотят взять к себе студентов и их обучить.
— Проблема известная. Дефицит в индустрии растет быстрее, чем академические учреждения успевают поставлять кадры. Рост индустрии — около 15% в год. И это очень много.
— Я бы разделял, всё-таки, индустрию прикладного софта и индустрию системного софта. Размеры индустрии прикладного софта раздуваются или сужаются в зависимости от того, что происходит на рынке: готовности инвесторов вкладывать в отдельные направления или стартапы.
А на программирование системного уровня, насколько я вижу, всегда есть спрос, потому что это фундамент, на котором работает всё. И больших колебаний спроса нет, потому что люди, делающие платформы, нужны всегда.
Про обмен технологиями, «научную» и «продуктовую» разработку
— А активно ли Java «тырит» технологии, фичи и идеи из других языков?
— Я бы не называл это «тырить», потому что в технологиях, например, рантаймов, существенная часть разработок делается либо в академии, либо в полуакадемических R&D Labs, которые публикуют научные статьи или технические отчеты о том как «попробовали такую вот идею. Выгорело / не выгорело». Люди, которые реализуют рантаймы, читают эти статьи: «Ага, это нам подходит, давайте попробуем у нас это реализовать». Понятно, что одну статью прочитают люди, которые пишут рантаймы под разные языки. Основной фундамент, где происходит подобного рода разработка – это полунаучный-полуиндустриальный сплав R&D.
— В России есть такие лаборатории сейчас?
— Для такой работы требуется уникальный набор навыков. Я не знаю полных лабораторий, которые были бы базированы в России, скорее отдельные люди, которые участвуют в таких разработках.
Если мы говорим про R&D лаборатории, которые финансируются индустрией, то граница между исследованием и прикладной реализацией довольно зыбкая. Часто это одни и те же люди.
— Известно, что многие инженерные проблемы в итоге решают ученые, а многие научные проблемы — решают инженеры. В прикладной математике такое встречается постоянно.
— В Oracle Labs есть люди, которые больше ориентированы на науку, которые пробуют решения в отрыве от продукта. И их результат работы — это технические отчеты или статьи. А есть продуктовые команды, которые в попытке улучшить продукт берут идеи из таких научных статей. При этом довольно часто внутри самого продукта рождаются какие-то решения, которые потом замечают и пытаются развить ресерчеры. Это такой симбиотический процесс. Это то, почему R&D и финансируется большими корпорациями.
— То есть ощущение, что компании в это вкладываются?
— Это не ощущение, я просто вижу это.
Про то, кто двигает OpenSource
— Чуть-чуть возвращаясь к вопросу опенсорса, и в частности Java. C одной стороны, ее развивает и двигает вендор, т.е. Oracle, с другой — сообщество, которое существует отдельно от организаций. В Java-экосистеме есть Даг Ли, которые сильно двигает Concurrency, но он при этом не работает в Oracle. Насколько это уникальная ситуация, когда лидер области находится вне организации?
— Не уникальная. Например, вещи, которые связаны с портами на альтернативные архитектуры, активно развивает не Oracle. АRM64, например в основном драйвится Red Hat, потому что Red Hat заинтересован в этой штуке. Еще есть условный Intel, условное AMD, которые тоже заинтересованы в том, чтобы сделать улучшения в кодогенераторах.
— А их видно вообще? Приходят ли к вам люди из Intel и AMD, говорят ли «вот вам оптимизация под наш последний процессор»?
— Они не могут так сказать. Они говорят: «Смотрите, если мы скодогенерируем вот так, то будет лучше. Вот наши перформансные данные». И если компиляторщики говорят, что это изменение действительно удачное, то все это принимается.
— А какой процент людей в Java-организации занимается низкоуровневыми задачами?
— Я никогда не считал. Если грубо, я бы сказал, что люди, с которыми я более-менее часто соприкасаюсь в своей маленькой области деятельности JDK, их, наверное, человек пятьдесят. Я, откровенно говоря, не знаю, сколько людей занимается какими-то другими фичами. Можно, конечно, посмотреть workchart и оценить, но там будет много тех, кто делает именно разработку.
— Сотни людей?
— Сотни две-три, я думаю.
— По твоим ощущениям, низкоуровневый кусок – это большой процент людей?
— Да, большой. Но все равно это задача настолько сложная, что этих людей все равно не хватает.
Про сложность низкоуровневых задач
— А почему задача сложная?
— Главным образом, потому что очень много движущихся частей. Очень много вещей, которые нужно знать, к которым нужно быть готовым. Ты пишешь компилятор, например, и тебе нужно знать, errat'ы процессоров. Знать, во-первых, что они вообще существуют (а для многих новость, что в процессорах есть баги), что тебе нужно будет эти баги посмотреть, чтобы понять, что не всегда в нестандартном поведении виноват твой компилятор. Ты должен знать, уметь и понимать, что баг, который ты сейчас фиксишь, может быть связан с какой-то дикой интерференцией прошлых преобразований кода, которые сделаны были до той части, за которую ты типа ответственен. Тебе нужно знать вот этот стек весь в глубину.
Рантаймы сам по себе — это такие продукты, в которых можно в крупную клетку выделить компоненты, но на самом деле эти компоненты очень тесно друг с другом связаны. Если тебе хочется фиксить баги, это часто означает, что тебе надо фиксить баги в разных компонентах, а если ты занимаешься перформансом, то точно ты будешь заниматься кучей компонент одновременно.
Я счастлив как ребенок, когда мой какой-нибудь перформансный патч занимает пять строчек в каком-нибудь одном файле, потому что это классное перформансное изменение, оно очевидно корректное и помогает. Но большие хорошие перформансные изменения обычно требуют изменений во всех маленьких местах всего этого большого продукта. Поэтому этот продукт нужно знать, а продукт огромный.
— Говорит ли это о том, что он плохо задизайнен?
— Нет.
— А почему тогда такие вещи происходят? Одним из критериев хорошего дизайна принято считать локальность: чтобы ликвидировать проблему, хочется нужно копаться в одном месте, а не в десяти.
— Это все прекрасно работает на бумаге. В реальности случаются две вещи: во-первых, когда ты начинаешь гнаться за перформансом, то, оказывается, что необходимо, чтобы абстракции протекали в каких-то отдельных местах, потому что именно так получается выигрыш. А во-вторых, всплывают баги.
Ты что-то знаешь о платформе, о том, как платформа себя ведет, что процессор, например, точно пересылает из регистра в регистр, когда ты говоришь ему «move». Если ты основываешься на этом предположении, ты можешь написать красивый компилятор, но тут внезапно оказывается, что в процессоре есть ошибка. Что ты будешь делать для того, чтобы это исправить? Ты вбиваешь в кодогенератор костыль. Потому что это практическое решение практической проблемы.
— И если у клиента стоит ферма, а на ферме 1000 битых процессоров...
— Если читать исходники HotSpot JVM, то можно увидеть там разные ужасы и самое главное — многие из этих ужасов подписаны. Например, можно встретить комментарии в духе «вот этот код написан уродски, но он написан уродски по таким-то причинам».
— А это правило вообще соблюдается?
— Обычно соблюдается. Когда ты фиксишь такие баги, от тебя ожидается, что ты напишешь, почему собственно ты сделал такую иезуитскую штуку.
И в таких местах обычно написано что-то вроде: «Наивный человек мог бы предположить, что здесь можно было написать иначе. Но здесь нельзя написать иначе, потому что преобразования в том-то месте сделают этот граф такого-то вида. И вообще пойдите и прочитайте по этой ссылке баг, там увидите пятнадцатистраничную эпопею о том, почему эта штука не работает так, как она должна была бы работать». То есть такие вот мелкие детали.
Hardware Transactional Memory
— Возвращаясь к errata'м и процессорам. В классической книжке Херлихи и Шавита есть отдельная глава, посвященная Hardware Transactional Memory. Ты мог бы чуть-чуть подробнее рассказать, что такое транзакционная память?
— Рациональность транзакционной памяти состоит в том, что есть проблема синхронизации, когда нужно сделать координированное изменение нескольких мест в памяти. Когда тебе нужно сделать атомарное изменение в одном месте памяти, то ты просто делаешь атомарную операцию.
Другое дело, когда тебе нужно сделать какую-то нетривиальную трансформацию, которую ты делаешь несколько чтений, несколько записей, тебе нужно сделать весь этот блок атомарным. Ты можешь сделать lock, сказать, что «мы здесь лок захватили, все там под ковром сделали, лок отпустили», и это с функциональной точки зрения работает.
Другое дело что, на этих локах будет что? Contention! Поэтому хочется получить некоторый хардварный механизм, которому ты можешь сказать «в начале транзакции запомни, что у нас было, потом под ковром я что-то сделаю в состоянии машины, а когда я сделаю коммит транзакции, то все это состояние машины атомарно покажется всем остальным». Это все и есть транзакция. У меня не просто записи и чтения индивидуальные, у меня целая транзакция, которая сразу все это состояние публикует или не публикует вообще ничего.
— Это похоже на CAS, который ссылку меняет.
— Да, можно это сделать CAS'ом, но там возникают проблемы – тебе там нужно врапперы делать, которые ты будешь CAS-ить, а тут ты как бы на голой памяти это можешь сделать.
— А врапперы влекут за собой Allocation, Memory Traffic...
— Да. HTM помогает избежать всего этого, обойтись без лишних созданий объектов оберточных. Ты можешь сказать, что, мол, «вот сейчас я начал транзакцию, я сделал 10 сторов в памяти, я коммичу транзакцию, и у меня либо все эти 10 сторов видны, либо ни один не виден».
— Как в базах данных?
— Да. Такая память поэтому и называется транзакционной, потому что это транзакция. Но для этого нужен хардварный саппорт. Потому что софтварные реализации транзакционной памяти уже были.
Софтварные реализации — они медленнее существенно, поэтому нужен хардварный саппорт. Нужно как-то хардвару объяснить, что если я исполняю команду «начать транзакцию», в этот момент машина говорит «ок, я прикину, что все что делается после начала этой транзакции пока никому не видно, а на коммите я все опубликую».
— Это прямо в ассемблерном коде есть инструкции типа «начать транзакцию»?
— xstart. Потом говоришь: xcommit, и тебе хардвар говорит, получилось у него закоммитить транзакцию или не получилось. xabort. Все прекрасно. Все ждали, когда появится хардварная транзакционная память. Azul в своей Vega давно делают транзакционную память, и они добились, как они говорят, успеха с эксплуатацией этой хадварной памяти HTM в Java.
— Только вот Vega померла.
— Vega не то, что померла. Гил Тене, CTO Azul Systems, говорил, что x86_64 стал настолько близок к Vega по перформансным характеристикам, что стало экономически не выгодно Vega саппортить.
— Да, железо саппортить дорого.
— Да и зачем? Когда есть хардварный вендор, у которого есть фабрика, и который продает тебе все за гроши. По сравнению со стоимостью собственного микропроцессорного производства — это сущие копейки.
И все обрадовались, и начали делать свои мелкие прототипы. Даже мы. Естественное место, где можно HTM в Java использовать — это когда у тебя есть, скажем, synchronized-блок тривиальный, в котором 2, 3, 4 store-а. Ты на входе начинаешь транзакцию, на выходе ее опускаешь. Семантика ровно такая же.
— То есть, JIT вдруг говорит, что теперь мы не локи используем, а используем вот такие хитрые транзакционные инструкции?
— И это даже было сделано чуть ли не в восьмерке. Но тут внезапно, как гром среди ясного неба, оказалось, что какие-то чуваки нашли баг в хардварной реализации этого самого HTM в Haswell. И поскольку этот баг, насколько я понимаю, был уже в кремнии, его исправить нельзя.
— То есть, схемка кривая?
— Да. Поэтому Intel перед всеми извинился и выпустил апдейт микрокодов, в котором HTM был выключен. Поскольку HTM — опциональная фишка, и чтобы ее использовать, ты должен флаг процессора проверить. Можно выпустить апдейт микрокода процессора, который скажет, что «я не поддерживаю». Это ошибка хардварного производителя, но такие штуки случаются иногда.
— С Pentium III был знаменитый отзыв процессоров. Видимо, такое случается раз в 10 лет.
— Не с Pentium III, а просто с Pentium, по-моему. Несмотря на то, что многие люди, как и я, купили Haswell в том числе для того, чтобы попробовать TSX, а потом внезапно оказалось, что твой процессор превратился в тыкву…
— Ты апдейтил в итоге микрокод или забил?
— Он автоматически апдейтится.
— А как это происходит?
— Апдейтит операционная система при загрузке. У нее есть специальный пакетик, в котором лежит микрокод.
— То есть для этого BIOS не надо апдейтить?
— Я так понимаю, что он делается через BIOS/UEFI, операционная система говорит процессору: «Вот твой новый микрокод».
— Это фактически есть уже у всех?
— Да, это нормальная стратегия с точки зрения функциональности, потому что там был баг, который повреждает память. Лучше медленнее, но корректней.
— А какие вообще дальнейшие планы у Intel на HTM?
— У них новая ревизия. По-моему, называется Skylake. Haswell рекламировался как «процессор, который поддерживает хардварную транзакционную память», а Skylake рекламируется как «процессор, который, наконец-то правильно поддерживает транзакционную память». Посмотрим, как в этот раз будет.
Про развитие Java-сообщества и бенчмарк-войны
— Когда Sun работал с комьюнити, было полное ощущение, что всем владеет Sun. С покупкой Oracle все испугались, что будет еще хуже. А сейчас у меня есть ощущение, что Oracle, наоборот, очень сильно инвестировал именно в развитие Java-сообщества. Насколько справедливо это ощущение?
— Когда ты рассуждаешь о таких вещах, нужно разделять субъективное ощущение от объективного. Sun, конечно, прекрасно работал с комьюнити, на конференциях рассказывал о том, как он развивается. Однако, если почитать отзывы на какие-нибудь JavaOne, которые Sun проводил, о том, что Sun объявляет в из года в год одними и теми же словами, что выпускают такую-то фичу. Можно просто по объективным критериям посмотреть, что и как. Сколько лет семерка выпускалась?
— 5 лет.
— Когда семерка была выпущена?
— в 2011 году.
— Когда Oracle купил Sun?
— В 2009-2010 году.
— Вот. Потому что Oracle, придя и купив Sun, сказал: «Ребята, хватит пытаться съесть слона целиком, давайте есть слона по частям. Вот у нас базовый набор фич, которые выходят в JDK 7 и мы выпускаем JDK 7, вперёд».
— Ты скорее рассказал о модели релизов, а меня больше интересует комьюнити.
— Мне сложно сравнивать, потому когда я работал в Sun, я не очень работал с комьюнити.
— Но ты же был в Intel, и вы там делали Harmony, насколько я понимаю. То есть ты видел все с той стороны. И это было еще до опенсорсинга JDK, по-моему.
— Да. OpenJDK вышла в 2007 году, а мы делали Harmony с 2004 по 2008. Тут история такая, что мало кого интересовала разработка самого рантайма до некоторого времени. Потому что было достаточно много вендоров, которые делали свой собственный JVM.
Был Oracle, который делал JRockit и стек, построенный на нем. Потом был и остается IBM, который делает J9. Был SAP и прочие, которые делали свои собственные JVM. То есть, была конкуренция между вендорами.
Я участвовал в так называемых «бенчмарк-войнах». Когда у тебя есть Java как стандарт, как спецификация и есть несколько разных ее реализаций от разных вендоров, а ты на бенчмарках показываешь, какая из этих реализаций круче. Это привело к довольно большим улучшениям в рантаймах, это нельзя отрицать.
Однако в этих бенчмарк-войнах есть один маленький минус — после определенного момента эти бенчмарк-войны обращаются в экономию на всяких спичках, которые не помогают реальным приложениям, а помогают конкретным бенчмаркам. И это нормально. То есть ты сначала оптимизируешь что-то, что помогает всем, а потом ничего не остается, как в конкурентной борьбе оптимизировать вещи, которые ты в здравом уме не стал бы оптимизировать вообще. Например, поставить перед HashMap'ом кэш, который кэширует первые двадцать тысяч лонгов. Ясно, что это не та оптимизация, которая нужна рядовому пользователю, она нужна конкретному бенчмарку.
Сейчас, по моему личному ощущению, бенчмарк-войны на софтварном уровне скатились на нет, на хардварном уровне они все еще происходят. И сейчас у нас есть OpenJDK как такой индустрия-образующий проект. Это коллаборация многих компаний. Если раньше у каждого была проприетарная реализация, каждый в собственной песочнице отверточкой что-то ковырял, то сейчас есть общая реализация, в которой реализована куча общей инфраструктуры для рантайма. И поэтому вменяемой стратегией является разрабатывать одну реализацию.
— А есть похожие на OpenJDK проекты с точки зрения влияния на индустрию?
— GCC, LLVM и подобного рода большие проекты. Опенсорс ведь рождается в том числе, чтобы экономить средства компании, чтобы каждая компания не изобретала велосипед. С одной стороны, выгодно использовать чужие разработки, а с другой, каждая компания имеет свои и делится ими с другими. Поэтому, мне кажется, сообщество относительно рантаймов стало развиваться с приходом OpenJDK очень сильно.
Возвращаясь к твоему вопросу. Я не думаю, что бурное развитие сообщества было связано с покупкой Sun компанией Oracle. Оно было скорее связано со структурой работы. Когда у тебя есть проприетарная реализация, у тебя меньше шансов сделать так, чтобы вендор тебя услышал. А если у тебя опенсорс, ты можешь спокойно делать у себя какие-то изменения, если окажутся хорошими — их можно отдать сообществу. Это та модель, которую пытаются сделать LinkedIn, Twitter и прочие. То есть, это скорее не про отношения компаний, а про подход к разработке, про структуру разработки.
Про мутабильность и иммутабильность
— В последнее время появился очень модный подход к разработке на immutable-объектах. Но неизменяемость порождает огромное количество локейшна, трафика, нагрузка на GC и удар по перформансу. Так нужна нам immutability или нет? Кто прав?
— Никто. Нет серебряной пули, забудьте об этом. Полностью залоканное приложение — это плохо. И полностью иммутабельное приложение — это плохо. Плохо по причинам, о которых ты сказал. Локи приводят к разного рода перформансным проблемам, проблемам с корректностью, с дедлоками и лайвлоками. С иммутабельностью ты можешь делать приложения, которые будут by construction правильные, но на реальном хардаваре, с реальными данными, с реально реализацией райнтайма, будут давать много перформансных эффектов из-за большого количества аллокаций.
Где лежит правильная граница между тем, как скрестить эти подходы — это открытый вопрос. Я хорошо понимаю и, скорее, прилежу к точке зрения, которую высказывают те, кто пишут на языке Scala и других экспрессивных коротких языках. Они говорят, и в этом они правы, что за производительность программы отвечает очень маленькая часть этой программы, поэтому первоочередная задача, которую ты решаешь в разработке — насколько ты быстро ты напишешь корректную программу. Поэтому эти люди говорят: «Давайте на Scala напишем все, сделаем хороший дизайн, и эта программа будет обозреваемой, читаемой. И мы будем знать, какие у нее параметры. А потом в нужных местах мы захакаем так, как нам надо» — и это вполне себе нормальный подход.
В Java мы делаем точно также. Ты пишешь на идиоматической Java, потом начинаешь что-нибудь перформансить. Заколачиваешь тут, сносишь объекты и переходишь на примитивные массивы там, убираешь вообще какие-нибудь доступы, расчехляешь Unsafe и начинаешь феерию и вакханалию устраивать… То есть ровно такая же история — языки нужны для того, чтобы удобнее решать целевые задачи. У разных языков разные целевые задачи, поэтому нет идеального языка. Я не считаю, что это плохо. Я не считаю, что этот подход является «хипстерским». Вполне нормально, что если ты пишешь на языке, который позволяет тебе быстро писать корректные программы, а потом еще дают возможность захачивать так, чтобы они были еще и быстрыми — ради Бога.
— Я тебе объясню, откуда взялась история про хипстеров. На конференции Java Tech Days в 2011 году, где мы с тобой познакомились, речь шла про развенчание перформансных легенд. Сейчас у меня есть ощущение, что вся эта история про immutability тоже стала City Legend и люди, которые про нее рассказывают, не очень сильно смотрят в корень…
— Люди любят бинарные ответы. «Локи — это плохо, а решения на CAS — это хорошо». Или «Java – это плохо, а Scala – это хорошо». Для меня это лакмусовая бумажка. Как только мне человек говорит, что что-то является идеальным решением вообще для всего — у меня в голове поднимается красный флажок, и я начинаю внимательно расспрашивать человека, на самом ли деле он так думает. Потому что, когда ты нарабатываешь опыт, ты понимаешь, что нет идеальных решений.
Мудрость опытного разработчика состоит в том, чтобы, посмотрев на проблему, понять, каким инструментом эту проблему решать. И менно за это нам платят большие деньги, а не за то, то, что мы сидим в офисе, развалившись на офисном кресле и пишем на форумах. От нас ожидают, что мы сможем под конкретную задачу выбрать инструмент, на котором можно дешево, сердито, корректно решить эту проблему. Вот в чем профессионализм состоит. Люди, конечно, будут повторять про погрешности, и это нормально, потому что у нас в голове есть принципы экономии мышления.
Конечно, у тебя есть наработанные общие правила, но очень легко забыть о том, что это не правила, которые работают в 100% случаев. Это правила, у которых есть границы применимости, они основаны на твоем полном или неполном понимании проблематики, которые основаны на текущем состоянии индустрии и т.д.
Одна из задач, которую я себе ставлю как перформансник, — находить ответы на перформансные вопросы, а не говорить просто заученными фразами «это хорошо, а это плохо». Нет. Ты должен понимать, когда хорошо «А», а когда хорошо «Б». И тот случай, о котором тебя спрашивают – это случай «А» или это случай «Б»? Тебе нужно выбрать подходящую штуку. Если бы не нужно было выбирать, меня можно было бы заменить простым скриптом, который будет говорить «да» или «нет». Природа сложна. Программирование (а это все еще часть природы, как бы нас ни учили, что это абстрактная штука) тоже сложно.
Про Unsafe
— Затронули тему Unsafe. Тут летом забомбило. Ты можешь рассказать какая у тебя позиция по этому вопросу?
— Фишка в том, что если у тебя есть какая-то спекуляция, то ты ее можешь спокойно написать в блоге, собрать кучу голосов и кучу обсуждений на форумах. А если ты авторитет, ты не можешь дать какой-то флеймовый ответ, ты должен над ним подумать, взвесить все «за» и «против». Это совсем другой уровень дискуссии.
То, что я наблюдал летом, это настоящая истерия, когда люди, которые не понимали, что происходит, начинали точить вилы и поджигать факела, чтобы идти и мочить девелоперов.
Дело в том, что Unsafe всегда был приватным интерфейсом. Это такая мусорная площадка, которая нужна для того, чтобы стандартная библиотека классов получала доступ к низкоуровневым фишкам. То, что можно было достать откуда-то unsafe и начать им пользоваться — это историческая случайность. Не было в Java таких уровней протекций, которые бы это запретили.
И люди начали писать на всяких StackOverflow и в своих бложиках: «Смотрите, что от нас злые разработчики прячут! Какое там богатство лежит, как мы можем это офигительно использовать!». И начали использовать. Несмотря на то, что Javac говорит им, что это проприетарный API и может быть убран в следующем релизе… А когда «внезапно» оказывается, что он будет убран в следующем релизе, то те почему-то удивляются!
Я понимаю людей, которые приводят аргумент, что если бы не было доступа к Unsafe, не родились бы какие-то продукты в джавовой экосистеме. Я также понимаю, что рефлекшном можно хакать некоторые части JDK. Но я не понимаю ситуацию, когда твой продукт и бизнес с огромным профитом зависят от приватного API нестандартизованного, а ты искренне удивляешься, когда этот API уходит, руша твой бизнес. У меня в этот момент возникает вопрос: «Где ваши чёртовы бизнес-аналитики, которые допустили такого рода оплошность? У вас 8 лет было для того, чтобы предложить решение, которое было бы стандартизованным, для того, чтобы ваш бизнес сохранить, чтобы появилось стандартное решение для вашей частной задачи».
Это нормальный подход к разработке продукта, это то, что комьюнити должно делать. Если хочешь какую-нибудь фичу, то ты вливаешься в ее разработку финансово, временем, инженерами, чем угодно. Опенсорс — это не то место, где тебе делают бесплатную работу. Опенсорс — это площадка, на которой тебе предоставляют возможность работать совместно, делать свои фичи и использовать фичи других. Это означает, что некоторые фичи ты будешь делать собственными руками, а не вендор будет за тебя все делать.
— В моем понимании, здесь есть 2 проблемы, одна из которых усиливает другую. Во-первых, отсутствие внятного евангелизма, что существует спецификация Java и существует реализация. Для многих было открытием, что «Java 8» — это спецификация, а «JDK 8» – конкретная реализация. Во-вторых, все это привело к тому, что сейчас люди до сих пор очень плохо разделяют все эти понятия. Не было ли это ошибкой со стороны Sun и Oracle, что они не стали сразу жестко «бить по рукам»?
— Пардон, что значит «жестко бить по рукам»? javac тебе говорит: «sun.misc.Unsafe is proprietary API and can be removed in future release». У тебя в Release Notes написано, что можно, а что нельзя делать с классами sun.misc. Там написано, что это проприетарные API, что не гарантируется, что они будут работать. Любой сотрудник Oracle годы тебе говорил, что Unsafe использовать нельзя, потому что это приватный API. Многие люди, которые использовали unsafe в своих проектах, говорили, что, если у вас продукт работает на unsafe, но у вас нет стратегии fallback'а, когда вам unsafe недоступен — у вас неправильный продукт.
— Но Unsafe используют многие. Я пилю какой-то стартап, смотрю, что есть на рынке, и ставлю, например, Hazelcast. И мне кажется, что у меня контракт с ними, что они мой вендор… Они не подумали, а я на этом построил свой бизнес. Получается, что идиоты в этой ситуации — все. Сейчас видно, что про это рассказывать нужно было больше…
— Мне кажется, что индустрия долгое время отрицала наличие такой проблемы. Тот самый чувак, который в Hazelcast пишет всякие статьи про то, как он героически нагибает Oracle, чтобы sun.misc.Unsafe сохранить, год назад на конференции Joker, он сидел с нами за пивом и говорил: «Да ну, вы никогда не выпилите unsafe!». А мы ему рассказывали, что Unsafe уйдет. И вдруг, год спустя это, оказалось какой-то гипер-новостью.
И вообще, нужно всегда помнить про различие между приватным и публичным. Если я разработчик, мне нужно сделать приватную реализацию, я использую средства языка, чтобы сделать ее приватной, а там уж, если вы своими грязными ручонками через рефлекшн залезли в этот API, то вы сами себе злобные буратины. Я свою программу написал так, чтобы к нему нельзя было доступиться нормальными средствами. Это моя приватная реализация, и я за это получаю право с этим приватным API делать все, что угодно.
— Ты очень правильную тему затронул. И проблема была в том, что в дизайне языка, если мы глубоко копнем, долгое время не было нормального инструмента, чтобы сделать нормальную инкапсуляцию. А что не запрещено – то разрешено… Тут, по-моему, удивляться поздно и надо что-то делать.
— Меня одновременно порадовал и огорчил один ответ, на одном из тредов на Mechanical Sympathy про Unsafe. Там пришел чувак, который сказал: «Знаете, в нашем продукте была точно такая же проблема. Как бы мы ни писали в нашей документации и блогах, мы не могли гарантировать, что люди не используют наши приватные API. В итоге нам пришлось, во-первых, не давать никакую документацию к этому API, а, во-вторых, даже менять от релиза к релизу реализацию».
Я вот читаю этот ответ и думаю: это вот то, что вы хотите? Если вы нарушаете правила приличия тем, что лезете в приватные API и требуете их стабильности, значит, подтолкнете разработчика этого приватного API к тому, чтобы они его спрятали еще сильнее. Хотя есть легитимные случаи и вменяемые способы использовать приватный API, например, обойти какой-нибудь баг. То есть ты, используя нештатно этот приватный API, спокойно можешь лишить себя возможности сделать «штатное» его использование.
Про JMH, бенчмарки и узкую специализацию
— Тогда вот такой вопрос. Ты последние три года активно занимаешься разработкой Java Microbenchmark Harness (JMH). Большинство коммитов делаешь ты, это практически твой проект, который сейчас под эгидой OpenJDK. Так?
— Это проект, который обслуживается перформанс-командой.
— И с ним есть одна проблема. Сказать «это быстрее, чем то. И это и есть доказательство» — это не доказательство, на этом анализ не заканчивается. Такое ощущение, что большинство людей вокруг этого просто не понимает.
— С JMH история следующая. Всегда нужно задавать себе вопрос — кому выгодно. Зачем перформансная команда делает JMH? Она делает его для того, чтобы облегчать нашу собственную деятельность, потому что у нас есть исследования, которые неизбежно ведут к бенчмаркам. Для того чтобы делать эти исследования, нам нужны инструменты, но инструментами это все не ограничивается. Потому что главная вещь, которую ты можешь достать из своего эксперимента — это не числа. Главное, что ты можешь сделать — это из чисел извлечь знание. Как правило, для того чтобы извлечь более-менее надежные знания, тебе нужна система теорий, каждая из которых должна быть подтверждена этими экспериментами. Ничего нового в этом нет — ты берешь философию науки и она ровно также сделана.
Перформансники по отношению к продукту — это как естествоиспытатели по отношению к природе. Мы строим высокоуровневые модели и делаем это посредством эксперимента. JMH помогает делать эксперименты, и главное слово в этой фразе – «помогает». Но не делает эксперименты за тебя. Помогает тебе не наступить на очевидные грабли в бенчмаркинге, для того чтобы сохранить время и разобраться с неочевидными специфичными вещами твоего эксперимента. Чтобы ты мог быстренько написать [стартовый — прим. ред] бенчмарк, потратить оставшееся время на то, чтобы понять, как правильно этот бенчмарк написать. А не тратить часы на то, чтобы исправить тупую ошибку с dead code elimination-ом, например. Вот для чего это нужно.
Он помогает решать легкие проблемы, которые все равно нужно решать в каждом эксперименте. Он не помогает решать специфичные проблемы конкретного эксперимента. Анализ нужен для того, чтобы понять, какой инсайт ты можешь дать из этих данных, можно ли этому инсайту доверять, какое место этого инсайта в общей системе твоих знаний.
Мы часто этим грешим, потому что когда ты пишешь какой-нибудь блог, делаешь бенчмарк какой-нибудь фичи — и мы там показываем эксперименты, которые таргетят конкретно эту фичу. На самом деле за этим экспериментом есть еще цепочка этих связей. Например, мы знаем, что этот harness нормально ведет себя на этой машине, что мы скалибровали эту машину, что она в thermal shutdown не падает. Или мы знаем, что такой-то подход к тестированию работает — мы это отдельно валидировали. В принципе, это тоже можно в блоге написать, но тогда это будет не блог, а целая книга о том, какие постановочные эксперименты мы до этого еще сделали, для того чтобы удостовериться, что тот эксперимент, который мы делаем сейчас — ему можно доверять. Нельзя просто так поставить бенчмарк и по-умолчанию считать, что бенчмарк корректный. Так не бывает. Бенчмарк является корректным, только если он тебе дает инсайты, совместные со всем остальным, что ты уже знаешь.
— Теперь смотри, что получается: мне надо узнать про перформанс, но я не очень большой дока в этом. Я ссылаюсь на некие авторитеты, на тебя, например. Делаю бенчмарк, замеряю, строю гипотезу о перфомансной модели, о конкретных инструкциях. Беру ассемблерный листинг, нахожу (или не нахожу) там эти инструкции из своего приложения — и вуаля, я проверил свою гипотезу. Фокус вот в чем: чтобы понять, какую именно инструкцию искать в этом самом ассемблерном листинге — нужно иметь бэкграунд, нужно без JMH уметь решать ту же самую проблему, решения которой я пытаюсь избежать, используя JMH. Так?
— Если ты хочешь ответ на вопрос в сложной тематике, в которой ты не разбираешься — ты должен найти человека, который в этой тематике разбирается и у него спросить.
Меня моя компания учит одной простой вещи: если я, допустим, отвечаю на какое-то письмо с юридическим вопросом и начинаю писать «I am not a lawyer, but…», то я должен закрыть это письмо, поднять трубку и позвонить настоящему юристу, который знает правильный ответ на этот вопрос. Ровно такая же история с перформансом. Ты можешь сказать: «Я, конечно, не перформансник и я не большая дока в этой штуке, но, кажется, перформансные данные показывают вот это». Но в этот момент ты должен сделать одно из двух: либо ты должен стать перформансником и нормально интерпретировать эти данные, либо ты должен пойти к человеку, который разбирается в этом вопросе и спросить его мнение.
Это одна из причин, почему в больших организациях, которые серьезно инвестируют в перформанс, есть перформансные команды. Потому что там хранят людей, которые умеют отвечать на такие вопросы. Не потому что сильно умные, а потому что у них есть опыт, система знаний. Их работа — держать в своей голове эти общие знания. А говорить о том, что я закрою глаза, посмотрю на эти данные, они подтвердят мое предположение — это confirmation bias.
Я, например, не буду спекулировать на тему того, какой из аппликейшн-серверов лучше. Я не знаю ответ на этот вопрос, я в этом разбираюсь, как свинья в апельсинах. Я, конечно, работал с аппликейшн-серверами, но там есть куча неочевидных вещей. И есть специалисты, которые в этом варятся, знают, что там происходит, и у них можно спросить совета. А для меня будет верхом тщеславия написать, например, в блог: «А вот я запустил что-нибудь на Glassfish, что-нибудь на Weblogic, Glassfish упал у меня с таким то эксепшеном, а Weblogic с таким-то эксепшеном. И из этого я делаю вид, что Weblogic лучше или Glassfish лучше». Ну это же глупость!
Я по каким-то обрывочным сведениям пытаюсь экстраполировать огромное количество знаний, которые я должен был бы, по идее, получать десятки лет. Так что максимум, что ты можешь сделать — это стать профессионалом в той области, в которой тебе нужны ответы, либо спрашиваешь у профессионалов в этой области. Все остальное — зыбкая земля.
Комментарии (12)
sunless
15.10.2015 12:30По поводу холивара про unsafe — основные притензии были в том, что хакрывая s.m.Unsafe, замену не подготовили. Да, когда-то будет varhandles, но, очевидно, очень не скоро. Unsafe использовали там, где небыло нормального api, он и сейчас не появился. При отсутсвии замены unsafe просто будет торпедироваться переход на следущие версии. Хотя в 9-ке unsafe останется, хоть и под флажком.
Поправьте опечатки: LVM -> LLVM, Java C -> javac
Quetzal
15.10.2015 12:47+2Советую посмотреть выступление Марка Рейнхольда на JVMLS:
Он подробно рассказывает о том, как будет «изыматься» sun.misc.Unsafe с попутным введением нормального API с тем же функционалом.sunless
15.10.2015 12:59+2И не менее познавательная лекция Пола Сансоса на том же JVMLS о том, какой функционал из unsafe будет доступен через VarHandles, а какой — нет. См табличку 3:20
sunless
15.10.2015 12:43+1А как тут править комменты? (притенизия->прЕтензия)
vedenin1980
15.10.2015 13:07+2никак, исправление комментариев доступно в течении трех минут, потом все, уже ничего нельзя исправить. Это такая фича у хабра.
Blooderst
15.10.2015 23:35+1Странные впечатления от этого видео. Начало было многообещающее, думал что услышу что-то про оптимизацию стрингов, на самом деле интересная тема, приготовился слушать настоящего хардкорщика… Не услышал ни слова конкретики про стринги, зато узнал какие эти низкоуровневые ребята крутые, как их мало и как они гордятся своей элитарностью. Это прямыми словами. Между строк услышал, что платформа сама по себе настолько заоптимизированна, настолько захардкожена, что изменения в нее вносятся с огромным трудом и тоннами вазелина. И все это ради увеличения производительности на доли процента. Ни о каком фундаментальном ускорении эти ребята даже не мечтают. Еще узнал про баги в процессорах и это было самым впечатляющим моментом в интервью, не пожалел что посмотрел.
Но осталось два вопроса:
1) Как ускорили стринги?
2) Какие именно баги и в каких процессорах находят корщики явистов?zzashpaupat
16.10.2015 01:55+6Про стринги и прочий перформанс надо ходить на конференции, JUG'и и т.д. Рассылки, опять же, есть, где можно задать вопрос. В конце-концов можно написать Алексею на почту и он ответит. Тут же просто интервью обо всем в целом и ни о чем конкретно.
Пафоса и элитарности особо не заметил.Artem_zin
16.10.2015 02:40+9+1, пафоса не увидел, «элитарность» — возможно, но правда, сколько JVM/JDK разработчиков вы знаете?
Шипилёв и Фёдоров душевные ребята, во всяком случае, Питерские JUGи оставили такое впечатление.
За пафосом это в Радио-Т или Разбор Полётов :)
Ни о каком фундаментальном ускорении эти ребята даже не мечтают.
Лол, ну, фундаментально могут только в Apple, каждый раз 2x, 3x faster, better.
Тюнить JDK и JRE сложно, но радует, что есть те, кто это делают, да ещё и рассказывают об этом на всяких конфах.
С тем же успехом можно сказать, что в плюсах фундаментально чё то ничё не ускоряют уже n лет, бездельники!
injecto
16.10.2015 11:07+5> Ни о каком фундаментальном ускорении эти ребята даже не мечтают.
Ну конечно, одна из самых производительных современных платформ каждый мажорный релиз должна как минимум 50% прирост производительности давать. (JVM вполне себе mature технология, фундаментальные вещи были оптимизированы в первых версиях)
> Между строк услышал, что платформа сама по себе настолько заоптимизированна, настолько захардкожена, что изменения в нее вносятся с огромным трудом и тоннами вазелина.
А вы, кстати, за микроядра или за монолитные? ;)
gurinderu
Интересные у Алексея задачи конечно.
Какова вероятность того, что на joker параллельные выступления останутся без слушателей и все пойдут слушать «The Lord of the Strings: Two Scours»?