Знакомство: о шифрованных демках и том, как попал в Xamarin
— Давай расскажем Хабру, кто ты, чем занимаешься.
— Я разработчик, уже лет десять работаю в стеке .NET, немножко работал в Java и совсем немного писал под Android.
Работал в разных компаниях: начинал с аутсорса, потом перешел в продуктовые, такие как Viber и Playtika. Потом я немножко пофрилансил, в том числе на Java, и пошел работать в Xamarin.
— Как ты туда попал?
— Я очень давно увлекался .NET и Mono. Мне нравился C#, но не нравилась политика Microsoft, которая его сильно завязала на Windows. Поэтому я следил за кроссплатформенной реализацией с момента ее появления.
Я активно следил за Mono, за Xamarin, как только он появился: мне нравилась сама концепция. Участвовал в их конкурсах и несколько раз занимал вторые места. Меня заметили и предложили поработать контрактором, причем написал сам Мигель де Икаса, что стало для меня полной неожиданностью, ведь для меня он был человеком-легендой.
— С чего ты начинал?
— Мигель предложил мне написать демо, которое включало в себя чат с end-to-end шифрованием под мобильные платформы. У меня был опыт работы с чат-приложениями и я увлекался темой шифрования, поэтому изначально меня взяли на бэкенд, но я сказал, что могу разрабатывать и под Android. После этого я занимался разными сторонними проектами Xamarin – меня не пускали в runtime и сами компоненты.
У Мигеля много интересных проектов. Иногда мне кажется, что это группа людей под одним именем. Ну не может один человек во всем шарить, всем отвечать, быть в курсе всего.
Я несколько раз делал для него демо для больших конференций типа Xamarin Evolve и MS Build – это самая большая девелоперская конфа у Microsoft.
А в чем была их коммерческая значимость этих демо, для чего они нужны?
Просто реклама технологии среди потенциальных клиентов. К примеру, одно из демо показывало пример как можно легко встроить 3D-визуализацию в обычное приложение на любой платформе и эта возможность заинтересовала несколько серьезных компаний в этой области.
О работе: задачи и вечный спор «удалёнка или офис»
— А теперь чем занимаешься?
— Меня перевели в команду runtime, то есть непосредственно в Mono. Моя главная обязанность — это мержить Mono и .NET Core, то есть быть где-то между двумя рантаймами. Это позволяет мне лучше понимать .NET, потому что я все эти типы, начиная с самых базовых и заканчивая сложными, исследую и досконально рассматриваю. За два года удалось нарастить хорошую базу опыта и познакомиться со всеми ключевыми разработчиками.
— Ты работаешь из дома?
— У нас есть небольшой офис Microsoft в Минске. Я периодически туда наведываюсь, но в основном из дома работаю.
— А что лучше: работать в офисе или дома?
— Для работы дома нужна большая самодисциплина. Периодически пробую совмещать это с путешествиями, но выходит не слишком эффективно. Мне, например, нужен полноценный здоровый десктопный комп с тремя мониторами. На ноутбуке я не могу комфортно работать.
— Тебе это нужно именно для мониторов или важна мощность компа?
— И для мониторов, и для мощности. Мне периодически нужно компилировать разные рантаймы: mono, coreclr, corert, крутить виртуалки и т.п. Для этого мне нужен полноценный топовый процессор, а не порезанное по TPD недоразумение, и, конечно же, быстрый SSD.
— То есть если ты хочешь работать над кодом Mono, тебе нужен нормальный комп?
— Mono включает в себя исходники .NET и .NET Core в виде сабмодулей, поэтому в итоге там огромное количество файлов, по которым надо как-то быстро перемещаться, поэтому самое главное — это быстрый SSD. Надо брать что-нибудь, начиная от Samsung 960 Pro и выше. Bottleneck всегда в IO.
— Опиши свой рабочий день
— Я работаю удалённо из Минска. Основная часть моей команды находится в США, хотя есть несколько человек в Европе, есть люди в Японии, Австралии, даже в Африке. Такая распределенная команда. Общаемся в основном в Slack, пару раз в неделю проводим митинги. Периодически встречаемся в Бостоне или Редмонде.
Задачи в основном довольно абстрактные. К примеру, портировать типы из определенного namespace. Я могу параллельно что-то брать, заходить на GitHub и фиксить какие-то баги. Периодически делаю что-то для .NET Core — пытаюсь что-нибудь оптимизировать или почистить.
— А откуда берутся задачи, как это организовано? Какой-то бесконечный Backlog?
— Задачи заводят пользователи и тим лиды, раз в месяц у нас есть неделя багфиксинга: целую неделю занимаешься только багфиксингом, другие дела бросаешь.
В остальное время также желательно не забывать про баги, но нужно придерживаться основных целей, к примеру моя цель — портировать основные типы из mscorlib и сделать Mono/Xamarin соответствующим NET Standard 2.1. Портирование типов обычно выглядит как выбрасывание старой реализации и заменой её ссылкой на код в .NET Core сабмодуль с адаптацией.
О Microsoft, осях и «предательстве»
— Ну да, лицензия позволяет. Да и вообще вы в одной компании.
— Да, позволяет. Мы и раньше так делали. Mono было частью некоторых дистрибутивов, по-моему, в Ubuntu и в GNOME даже было Mono. Мигелю говорили, что он всех под монастырь подведет.
— Да, я помню, его Столлман называл предателем.
— Боялись, что в любой момент могут нагрянуть адвокаты Microsoft и всех засудить, чего Microsoft, к счастью, так и не сделал.
— Ну да, Microsoft сделал прямо противоположное — стал Linux использовать у себя.
— Microsoft сейчас совершенно другой при новом СЕО, фокус на облачных технологиях привел нас в мир опенсорса и всего того, о чем раньше и подумать не могли. Сейчас возможно скачать Ubuntu WSL из Marketplace одним кликом, задеплоить MS SQL Server на Linux и разрабатывать под .NET из под macOS.
— То есть вы можете спокойно писать код под открытыми лицензиями и никто ничего не скажет?
— Да, конечно. Естественно, перед тем как выложить какой-нибудь внутренний проект в опенсорс нужна небольшая бюрократия, но в целом, я не встречал запретов на использование чего-либо.
— У тебя бывают задачи, которые требуют сразу трёх платформ?
— У меня целый набор: один компьютер на Windows, MacBook с macOS и ноутбук с Fedora. Также целая россыпь виртуалок, включая WSL. Чаще всего баги делятся на два типа — Windows и не-Windows, которые воспроизводятся как на macOS так и Linux.
Разбираемся с .NET Core и Mono
— Какие есть направления, которые тебе нравятся, и их можно развивать в .NET Core и в Mono?
— Лично мне нравится большой упор на производительность и кроссплатформенность. Производительно постоянно улучшается в боевых условиях начиная от Bing и заканчивая публичными бенчмарками типа TechEmpower, в которых .NET Core показывает себя с очень хорошей стороны наравне с решениями на базе Go, Java и С++. У многих людей до сих пор есть стереотип о .NET, как Windows-only технологии с тормозной виртуальной машиной — с этим стереотипом мы и успешном боремся.
Наша команда большое внимание уделяет АОТ сценариям и использованию LLVM в качестве бэкенда для генерации машинного кода. LLVM — очень мощный инструмент с огромным количеством оптимизаций. Нужно лишь аккуратно сгенирировать LLVM IR с минимальным количеством safe-points, чтобы не мешать этим самым оптимизациям. Лично я не так давно даже написал свой простой LLVM transformation pass.
Также радует, что C# и .NET являются мейнстримом наравне с С++ в геймдеве благодаря Unity и некоторым другим движкам, которые имеют C# скриптинг.
Есть потенциально интересное направление — компиляция C# в Web Assembly для браузера.
— Не знаю, как в .NET, но порой приходится тащить кучу стандартных библиотек для компиляции. В Java ты запускаешь Hello World, а у тебя грузится 2 тысячи классов. В браузере будет грузиться нехилое количество мегабайт. Что ты по этому поводу думаешь?
— Минимальный размер рантайма Mono с базовой библиотекой что-то около двух мегабайт. Но это проблема есть даже у Apple: приложения, написанные на Swift тащат каждое свой рантайм. Пока технология Mono-wasm сыровата и базируется на рантайме, который был АОТ скомпилирован в WASM + интерпретатор для пользовательского кода. Кстати, рантайм сейчас вот переписываем с С на С++, надеюсь, это не повлияет на размер в итоге.
— А вы не пробовали переписать Mono на C# вместо плюсов или C?
— Идея звучит неплохо, но потребовала бы просто нереальных ресурсов и у нас есть некоторые подвижки в этом. Команда .NET Core дошла до такого уровня C# и .NET, что плюсовый код заменяется на C#, чтобы не париться с кроссплатформенностью и при этом производительности он не теряет. Недавний пример — перевод реализации парсинга и конвертирования числовых типов и весь Decimal были переписаны на C#. Меня это очень радует и сильно упрощает работу по миграции кода.
О Garbage Collector
— Я видел .NET Core GC, которым пугают детей, потому что это полтора мегабайта исходника на C++! Полтора мегабайта, Карл! Вот это сколько книг?!
— Да-да, при этом в этом файле отметилось 47 контрибьюторов согласно гитхабу. Я не специалист по Garbage Collector, но вообще GC имеет под собой довольно общую теорию типа алгоритма Mark-n-Sweep, который усложняется поколениями и попытками максимально избежать полных остановок мира и делать всё параллельно основному потоку выполнения.
— У вас есть плагины или возможность менять Garbage Collector или он один?
— В Mono есть несколько реализации, а в .NET Core не так давно сделали публичный API, которые позволяет взять пару хедеров, написать свой ГЦ и подключить его в любое приложение одной переменной среды. В качестве примера есть статья о том, как написать ZeroGC для .NET Core. В мире контейнеров, где не обязательно убирать за собой мусор может быть актуально. В целом это позволяет кому-нибудь, к примеру, взять текущую реализацию и максимально оптимизировать ее для, допустим, геймдева, чтобы остановка мира и пробежка по всем объектам не лихорадила FPS к примеру или оптимизировать потребление памяти, по-моему ребята из Samsung так сделали для Tizen пару модификаций в GC.
— То, что Microsoft отпустил тотальный контроль над всем — это хорошо, ведь GC и JIT — это очень хороший инструмент контроля.
— Да. Посмотри на .NET Foundation — это ведь уже не только Microsoft. Там Google, Red Hat, Samsung, Intel, в общем, все компании, которые раньше, казалось бы, рядом с Microsoft стоять не будут. Разве что Apple не хватает.
О поддержке IDE
— Насчет IDE: насколько хороша в тулинге, в самом и в компиляторе в поддержке IDE? Сейчас есть всякие штуки типа Swift, где компилятор даёт очень мало возможностей поинтраспектить внутреннюю структуру, покешировать, ещё что-то. И это бесконечная боль, потому что тебе, когда делаешь какой-то свой тулинг, надо заново переизобретать весь мир. Насколько хорошо с этим в Mono? У вас своя IDE?
— Компилятор C# Roslyn изначально писался как не только компилятор C# в IL, но и бэкенд IDE и анализатор, он умеет переваривать даже плохой код. Ты можешь на основе его output просто показывать какие-то вьюшки и что-то делать, а он будет прямо говорить: «Покажи там менюшку», «предложи рефакторинг», «вот тебе превью изменений» и т.п..«выдели, вот такой рефакторинг и предложи юзеру». То есть этот компилятор прямо позволяет тебе быстро сделать свою IDE.
По сути, ты просто реализуешь набор интерфейсов для своего GUI, а у тебя уже есть IDE, которое поддерживает большой набор рефакторингов и тому подобное.
В целом, многие современные языки позволяют получить AST — абстрактное дерево выражений кода. Например, Clang отлично позволяет из плюсового кода получить абстрактное дерево, мы, кстати, используем эту особенность для генерации C# байндингов к С++ и Objective C коду.
— Ты пробовал использовать Visual Studio Code для чего-нибудь?
— Ну я бы сказал, что это самый основной мой инструмент.
— Допустим, чувак хочет открыть репозиторий Mono и похачить его. Что ему для этого нужно?
— На Windows просто открыть cолюшн рантайма и солюшн бцл и сбилдить оба. Благодаря эффективной параллелизации msbuild должен справится минут за 5. На macOS и Linux используется привычный подход через Makefiles.
О подготовке докладов и немного спойлеров
— Ты же с докладом приезжаешь на DotNext, а про что он будет?
— Мой доклад будет состоять из набора интересных примеров микрооптимизаций, примененных в самом .NET Core разработчиками и сторонними контрибьютерами, которые, мне кажется, могут быть полезны и прикладным программистам. Также уделю внимание неудачным примерам что-то заоптимизировать, к примеру, когда контрибьюторы хотят оптимизировать какой-то конкретный случай, но выходит это боком в виде регрессии в других. Отдельно будет десяток слайдов по новоиспеченному API к SIMD.
Ребята из Intel вместе с Microsoft-ребятами вывели наружу в C# низкоуровневое API для SIMD, который позволяет писать сверхбыстрые алгоритмы не полагаясь на компилятор, который, как многие думают, сможет сам всё что нужно оптимизировать и векторизовать — так не бывает.
— В общем случае это теоретически невозможно.
— Да, нигде не уйти от самостоятельной вставки интринсиков. Сомневаюсь, что в каком-либо языке можно описать перемножение или транспонирование матриц на простых типах и ждать от компилятора максимально эффективные SSE/AVX инструкции на выходе. Кстати, я уже применил эти C# интринсики внутри .NET Core для оптимизации System.Numerics.Matrix при помощи SSE и оптимизировал функцию GetHexDigits при помощи Lzcnt. Можно использовать как пример использования API в своих проектах.
— Когда приходят люди, которые разрабатывают что-то core-ное, ещё приходят те, кому интересно тоже в этом поучаствовать. Есть ли какой-то путь новичка?
Любой first time contributor получает большое внимание и помощь, многие простые задачи или баги, которые не требуют объемных знаний и высокого приоритетах могут помечаться специальным лейблом на GitHub — «up-for-grabs», либо «good first issue».
— Можно зайти на репозиторий, найти по этим меткам issues и выбрать близкий по духу. Например, довольно много задач о покрытии тестами каких-то кусков кода. Увеличение coverage тестами, — это вот прямо идеальная первая задача. Также хороший способ — это что-то побенчмаркать, сравнить с другими рантаймами и попытаться разобраться почему тот или иной код работает медленнее чем в .NET 4.x, к примеру string.GetHashCode. По бенчмаркингу есть большое количество выступлений и блогпостов от Андрея Акиньшина и Адама Ситника про очень удобный инструмент — BenchmarkDotNet, который простым движением руки — одним атрибутом покажет вам скорость выполнения кода, сравнит с другими рантаймами, расскажет за память и покажет ассемблерный код.
Т.е. минимальный набор действий — это просматривать все пулл-реквесты и задачи, подписаться в твиттере на таких людей как Matt Waren и Ben Adams, зайти в каналы corefx и coreclr в гиттере ну и прочитать документацию по BenchmarkDotNet.
— Да. Я вот сейчас отфильтровал тегу up-for-grabs, здесь около 600 issues, некоторые вообще без комментариев и их можно брать.
— Да, всё так. Ещё недавно проводили хакатон для .NET Core-команды. Выделили пару десятков issues-ов, и за день их нужно было пофиксить и получить за это приз.
— Это отлично. Рассказал много интересного, теперь хочу попробовать сам какую-нибудь issue зарезолвить. Правда, я не знаю C#, вот в чем проблема.
— C#, как мне хочется верить, довольно предсказуемый язык не смотря на больше количество сахара и обладая опытом в Java или С++, думаю, можно довольно быстро начать даже что-то оптимизировать в рантайме, опыт в других языках в этом даже поможет посмотреть на вещи с другой стороны.
— Я сейчас смотрю на репозиторий .NET Core и он выглядит очень прилично. И люди действительно общаются в комментах, прямо дискуссии проходят.
— Да, довольно активные. Там их и 100, и 200 комментариев. А учиться можно по базовой библиотеке классов, там довольно много интересных задач, которые может взять любой человек.
— Спасибо тебе большое за ответы! Встретимся на DotNext.
В этот раз минутка рекламы будет необычной, потому что пока мы готовили интервью, билеты на конференцию кончились. Хотите посмотреть доклады и не успели купить билет? Онлайн-трансляция все еще доступна на сайте.
Если у вас есть вопросы или невероятное желание посетить DotNext 2018 Moscow лично, напишите нам на tickets@dotnext.ru (возможно, кто-то вернет билет, и мы сможем вам помочь).