Julia – мой любимый язык программирования и основной рабочий инструмент для проведения научных исследований и подготовки научной графики. Я восхищаюсь её простотой, изящностью и производительностью. Именно благодаря Julia я вошёл во вкус и начал получать удовольствие от самого процесса программирования. Иногда могу программировать что-то с утра и до вечера несколько дней подряд, но при этом я не являюсь в полной мере ни программистом, ни работником IT-отрасли. У меня нет полноценного IT образования и я никогда не работал программистом. В некотором смысле я являюсь именно тем, для кого разрабатывался язык - я учёный, исследователь. Моя работа всегда была связана с геологией, а программирование было только способом автоматизации каких-то операций или получения результата, недостижимого с использованием существующих средств. Года три я программировал на R, потом перешёл на Julia. И вот, по прошествии двух лет, я хочу поделиться некоторыми проблемами, которые я вижу у Julia и её экосистемы. Не чтобы пожаловаться, а чтобы предупредить и подготовить тех, кто только приступает к освоению этого прекрасного языка, или только присматривается к нему. В сети много восторженных статей двух-трёхлетней давности, есть и современные разборы проблем от профессиональных программистов. А я хочу постараться передать взгляд учёного, простого пользователя, решающего с помощью Julia свои повседневные не самые сложные задачи.
Итак, вот вещи, которые стоит иметь в виду:
1) Julia лучше всего подходит для открытых проектов или сервисов. Язык формально компилируемый, и в принципе есть способы получить автономный исполняемый бинарник, но они достаточно нетривиальны, и бинарник относительно простой программы в итоге может весить несколько гигабайт. Если предполагается использовать Julia для научного программирования, где код является частью научной публикации, или для разработки сервисов, где потребитель никогда не увидит кода – никаких проблем нет, она здесь идеально подходит. Никакие автономные исполняемые бинарники не нужны, можно брать и пользоваться. Но если вдруг потом захочется на основе полученных наработок сделать какую-то коммерчески распространяемую автономную программу – могут возникнуть сложности, которые могут потребовать в том числе и переписывания всего кода на каком-нибудь другом языке, предполагающем компиляцию в компактный автономный исполняемый файл. И тут мы подходим к следующей проблеме.
2) Официально заявлялось, что Julia призвана решить «проблему двух языков», заключающуюся в том, что для проведения научных расчётов часто приходилось выполнять прототипирование на языке, удобном для прототипирования (Matlab, Python, R), а затем переписывать полученный код или какие-то его фрагменты на другом языке, оптимальном с точки зрения производительности (C, С++, Fortran). Действительно, использование Julia позволяет одновременно получить и элегантный читаемый код, исполняемый на лету, и высокую производительность этого кода. Но, как уже отмечалось выше, получить компактный исполняемый бинарник с помощью Julia на текущем этапе развития проекта скорее всего не получится. Так что если одним из требований к результату помимо высокой производительности будет компактность исполняемого файла, то код на Julia всё равно придётся переписывать на C, С++ или Fortran. Так что от проблемы двух языков пока что полностью избавиться не получилось.
3) Даже достаточно базовые пакеты всё ещё не очень стабильны в плане воспроизводимости результата. При запуске своего же кода после обновления пакетов легко получить сильно отличающийся результат. Например, после одного из недавних обновлений я с удивлением обнаружил, что случайное число на основе того же стартового значения (seed) теперь считается по-другому, что полностью поменяло вид графиков, генерирующихся уже имеющимся кодом. Я всего лишь хотел добавить ещё одну картинку для статьи, а в итоге получил ситуацию, где нужно либо перегенерировать все уже имеющиеся картинки, либо откатиться к прошлым версиям пакетов и сгенерировать дополнительную картинку с ними, чтобы все картинки были в едином стиле. Как показало дальнейшее изучение вопроса, изменение было плановое, официально объявленное в Release Notes для Julia 1.7. Я не ожидал такого от промежуточной версии, поэтому не читал внимательно, а зря. И это только сама Julia, а ведь есть ещё и пакеты, где подобные изменения случаются значительно чаще.
Приходится отслеживать версию Julia и пакетов, в которых код был создан, иначе тот же код может дать другой результат или не запуститься. Для научных статей это является особенно серьёзной проблемой. Ведь у читателя вашей статьи, к которой вы приложили фрагмент кода или ссылку на репозиторий с кодом, этот код тоже может дать совсем другой результат, чем в статье. Особенно, если с момента публикации пройдёт несколько лет. Как доказать, что на момент публикации всё нормально работало и вы как учёный тут никак не виноваты, что тут не умышленный подлог, а ситуация нарушения обратной совместимости со стороны языка и используемых пакетов? Самый простой способ – опять же, указывать в самом коде версию языка и пакетов, на которых всё должно правильно работать.
Но всё равно после любого обновления (а обновление может произойти просто при установке дополнительного пакета, который вдруг понадобился для какой-то сиюминутной задачи) стоит быть готовым к тому, что какое-то количество мест во всём ранее написанном коде может прийти в негодность. При открытии старого кода, который какое-то время не трогал, приходится закладывать время на его исправление под требования современных версий Julia и используемых пакетов.
4) Набор базовых пакетов в сборе занимает несколько гигабайт. Это не является проблемой само по себе, но время от времени, у меня по крайней мере, возникает каскадный отказ, когда менеджер пакетов не может разрешить зависимости, и при добавлении какого-то нового пакета, который требует несовместимых версий уже имеющихся, всё приходит в негодность. К счастью, такое происходит редко, где-то пару раз в год. Обычно помогает полный снос всего каталога с пакетами и установка всех пакетов заново. Никто не может точно сказать, в чём причина данного явления, не было обнаружено и какого-то более изящного способа решения проблемы. Наверное, если бы я был увлечённым IT-специалистом, я бы пару дней покопался сам и в итоге нашёл причину проблемы и способ всё поправить, но для меня распутывание таких задачек не вызывает ни удовольствия, ни интереса, просто времени на это жалко. Проще всё переустановить. Один раз была ситуация, когда после удаления директории и пересборки всей системы пакетов на том же проблемном пакете снова произошёл такой же каскадный отказ. Решилось пересборкой пакетной системы ещё раз, но в этот раз без пакета, который рушил систему зависимостей. А каждая пересборка системы пакетов – это значит надо из сети выкачать несколько гигабайт. Хорошо, если канал хороший, и произошло это не в командировке или отпуске с полуживым гостиничным Wi-Fi.
5) Julia имеет достаточно большие аппетиты в плане памяти. В бенчмарках, где сравнивается производительность программ на разных языках, обычно всё внимание приковано к скорости исполнения, где идёт ожесточённая борьба за лидерство. Здесь Julia на равных соревнуется с C, С++ и Fortran, иногда чуть-чуть отстаёт, иногда опережает. Но если посмотреть на потребление памяти – то оно почти всегда больше, и часто не на проценты, а в несколько раз. На этом моменте как-то обычно не акцентируется внимание, но такое явление есть. Вроде как работа в этом направлении ведётся, и в будущих версиях аппетиты Julia планируется уменьшить. Но если говорить про настоящее время, то аппетиты эти довольно высоки. На относительно современном ноутбуке с 16 Гб оперативной памяти в своих задачах я обычно не замечаю эту прожорливость, у меня довольно редко случаются вылеты из-за нехватки памяти. Но на машинах с меньшим количеством памяти или при более сложных расчётных задачах это может быть проблемой.
Один из хороших примеров для иллюстрации данного утверждения - результаты бенчмарка The Computer Language Benchmarks Game. Это, конечно, не абсолютно объективный результат, поскольку разные реализации программ на разных языках пишут разные люди, с использованием разных идей по оптимизации производительности кода, плюс неизбежно вносятся некоторые искажения, если рассматривать только самые быстрые реализации программ. Но поскольку сравнение проводится на наборе из нескольких задачек, некоторая закономерность всё же прослеживается. Вот графики скорости выполнения и объёма кода, которые я взял из книжки у Bogumił Kamiński, немного переделал на свой вкус и обновил по наиболее свежим результатам от 05.22:
Вроде бы всё хорошо: Julia действительно может быть быстра и имеет лидирующие позиции по компактности кода. Но если мы посмотрим на объём потребляемой памяти, то видим уже совсем другую картину. В книжке этот график почему-то не приводится:
Видим, что реализации на Julia почти всегда потребляют существенно больше памяти, чем реализации этих же алгоритмов на C или Fortran. Результаты для Julia при этом во многих случаях отличаются от результатов для C и Fortran на некоторое близкое к константе значение. Задачки в тесте достаточно простые, так что есть надежда, что эта же константная дельта сохранится и при увеличении сложности задачек. Возможно, именно поэтому графики потребления памяти обычно и не приводят. Но, во-первых, открытые результаты тестов на тяжёлых задачках мне не известны, и во-вторых, вряд ли кто-то будет запускать серьёзные ресурсоёмкие вычисления на типовом ноутбуке с 8 или 16 Гб памяти. А для бытового использования избыточное потребление памяти у Julia всё же стоит иметь в виду.
6) Проработка документации очень неоднородна. Где-то она подана как первоклассная книга, чтением которой можно случайно увлечься, а где-то есть зияющие провалы, когда какие-то ключи функций или синтаксические конструкции не описаны совсем. Особенно это касается пакетов. Но ведь для прикладного использования Julia нужна именно с пакетами. Конечно, настоящие программисты могут посмотреть всё по коду, что там как внутри происходит, и сами разгадать, что и как нужно записывать, но для пользователя-учёного, использующего только какое-то подмножество языка, прочесть серьёзный чужой код достаточно сложно. Как минимум, на то, чтобы разобраться с ним, потребуется много времени. В контексте научной работы - времени отвлечения от своей основной работы. Так что для нормальной работы пользователю-учёному нужна документация к используемым функциям. Здесь, конечно, с ностальгией вспоминаются странички R по каждой из функций языка. Типа такой, такой, и так - по всем функциям. Некоторые даже со ссылками на используемые научные работы, для научного использования - это необходимость. У многих пакетов R документация - это многостраничный pdf с картинками и примерами кода. У Julia, и особенно у её пакетов, такой качественной документации пока нет. Приходится спрашивать совета у знающих людей, подсматривать чужие примеры кода и экспериментировать. А на это всё неизбежно уходит время. Это не проблема для хобби-проекта, но может быть проблемой при попытке использования в реальной работе.
7) Язык и библиотеки стабилизировались относительно недавно, поэтому готовых рецептов, как получить то или иное, всё ещё не очень много. Ситуация не такая проблематичная, как два-три года назад, когда многие рецепты в сети относились к старым версиям Julia и просто не работали, но всё ещё далека от идеальной. Если захочется совершить какую-то нестандартную операцию или получить какую-то нестандартную графику, то придётся какое-то время побыть первооткрывателем. Это приятно е ощущение, но на все эти открытия тоже неизбежно уходит время. Опять же, это не проблема для хобби-проекта, где нет никаких дедлайнов, но в реальной работе может доставить хлопот.
8) Эта проблема уйдёт со временем, но по Julia всё ещё маловато специализированной литературы. Хочется видеть что-то вроде «Julia для задач экологии и природопользования», «Julia для прогнозирования временных рядов», «Julia для картографии» и прочие подобные издания, но пока этого нет. По самому языку уже есть какое-то количество хорошей литературы, много информации можно почерпнуть из документации к языку и пакетам, но специализированная литература пока крайне скудна. Здесь же отмечу, что до сих пор нет ни одной печатной книги на русском по современной версии языка. Мне кажется, было бы беспроигрышным вариантом перевести «Hands-On Design Patterns and Best Practices with Julia: Proven solutions to common problems in software design for Julia 1.x» или «Think Julia: How to Think Like a Computer Scientist», но пока издатели не спешат этого сделать, или работа уже идёт, но нам готовят сюрприз. Кто-то скажет, что такую литературу надо читать только в оригинале, и в этом действительно есть своя правда, но что делать, если от чтения на английском утомляешься быстрее, чем от чтения на русском, и в итоге полезной информации за раз получаешь меньше?
9) Эта проблема тоже уйдёт со временем, но к Julia в научном сообществе нет пока того доверия, какое есть, например, к R в области статистики. Особенно, если речь не про саму Julia, а про пакеты, многие из которых ещё не до конца стабилизировались. Там могут быть (и есть) ещё не выявленные и не закрытые ошибки, а экосистема языка ещё слишком молода, чтобы говорить, что любую строчку кода пробежала уже тысяча глаз. Ну и как показывает детальный разбор, опасения эти не беспочвенные. Да, наверное при глубоком погружении какие-то ошибки могут быть обнаружены даже в достаточно базовых пакетах. И тут уже встаёт выбор: пытаться исправить самому, если позволяет квалификация и время, или ждать решения от авторов и сообщества. Но при типичном повседневном использовании ошибки практически никогда не возникают. В типовом случае, если Julia или какой-то из пакетов работает не так, как я ожидаю, то это почти на 100% не ошибка в Julia или каком-то её пакте, а ошибка в моём понимании принципа работы какой-то конструкции Julia или её пакта. За всю практику работы я нашёл только одну серьёзную ошибку в одном из пакетов, завёл задачу на исправление и автор в тот же день поправил.
Что же касается приведённой выше статьи, то мне кажется, это во многом эффект привыкания к хорошему. Пакеты Julia умеют взаимодействовать между собой, как части единой системы. Это похоже на магию, с этим очень удобно жить, и конечно к этому быстро привыкаешь. Но поскольку пакеты ещё слишком молоды, в некоторых случаях эта "магия" нарушается, и поведение, корректное в рамках каждого из пакетов по отдельности может давать ошибку при их совместном использовании. Конечно, это происходит в самый неподходящий момент, и это может быть очень обидно. Конечно, нужны дополнительные договорённости, которые позволят обеспечить ещё более тесную интеграцию пакетов. Прекрасно, что эта проблема была так чётко сформулирована и её обсуждают. Для дальнейшего успеха экосистемы Julia её надо решить, и как можно скорее. Но при типичном повседневном использовании эта проблема обычно не наблюдается. Поэтому выносить её как отдельный пункт я бы не стал.
10) Это даже не недостаток, но для кого-то может быть критичный момент. Для максимально удобной работы с языком нужен либо VSCode, либо Juno или Jupyter, или хотя бы Atom. Это всё на основе веб-технологий. Для тех, у кого непереносимость веб-технологий, это может вызвать отторжение. Но набирать команды напрямую в консоль, либо писать в блокноте и потом запускать, по моему опыту очень непроизводительно. Какая-то поддержка Julia есть и в других IDE, но большинство пользователей использует VSCode, Juno, Jupyter или Atom, поэтому если есть потребность найти какое-то отличающееся решение, то этот вопрос скорее всего придётся изучать самостоятельно.
Julia была задумана как язык, совершенный во всех отношениях, но в реальности абсолютное совершенство очень труднодостижимо. Где-то тебе зачтут за недостаток просто твою молодость и следующие из этого проблемы. Это неизбежно. Я по-прежнему считаю Julia оптимальным решением для своих задач, переношу на неё свой старый код с R (хотя, как я показывал, их достаточно удобно можно использовать и вместе), и не вижу на горизонте никакой другой сопоставимой по совершенству системы, на которую можно было бы со временем перейти. Я намеренно не стал включать в список проблем отсутствие у Julia поддержки объектно-ориентированного подхода, поскольку для научного программирования это больше похоже даже на плюс, чем на минус. Я не вижу большой проблемы в задержке на несколько секунд перед первым запуском пакетов, тем более что есть способы, как эту задержку ликвидировать, и ведётся работа, чтобы эта задержка в будущих версиях стала меньше. Некоторые вещи, например, отсутствие возможности программировать на Julia напрямую под Android, я принимаю как данность, хотя если такая возможность появится, то, наверное, буду активно её использовать и мне станет тяжело от неё отказаться. Также и отсутствие пакетов по некоторым направлениям нельзя на мой взгляд записывать в недостатки языка. Опять же, всегда можно воспользоваться механизмом включения пакетов из Python или R. Неоднозначна ситуация и с количеством открытых вакансий, которую иногда приводят как недостаток. С одной стороны это можно сформулировать как недостаточно высокую популярность языка, а с другой - как уникальные возможности для специалистов, знающих Julia, которые в данный момент нарасхват. Даже меня пытались хантить как знающего Julia, хотя я не программист и не ищу работу. Можно ещё вспомнить, что почти нет хороших русскоязычных учебных курсов. Единственных хороший, который я знаю - вот. С другой стороны, наверное даже хорошо, что пока ещё не открылись лавочки, предлагающие курсы вроде "Стань специалистом по Julia за неделю" с сертификатом и помощью в устройстве на работу.
Я по-прежнему могу рекомендовать Julia в качестве первого языка программирования, особенно для тех, чьи задачи связаны с научным программированием, обработкой и анализом данных. Для тех, кто хочет только прикоснуться к миру программирования, могу посоветовать начать знакомство с Julia с её использования в качестве системы подготовки научной графики. Здесь она тоже на высоте. Так я начинал когда-то своё знакомство с R, и Julia тут ни в чём не уступает. Некоторые решения даже более изящны.
Пользуясь случаем, напоминаю про приближающуюся ежегодную конференцию JuliaCon 2022, которая пройдёт в онлайн-формате 27-29 июня, но некоторые мероприятия которой начнутся уже с завтрашнего дня. Доступна бесплатная регистрация.