Поскольку я 5+ лет провел в JB, конторе которая пилит IDE, у меня накопилось много опыта и мнений насчет того как эти «ИДЕ» стоит строить. Сразу скажу, что непосредственно в разработке IDE я практически не участвовал — как я уже говорил, в JB я попал в то странное время в моей жизни, когда на «карьеру программиста» мне было чуть более чем совсем, так что становиться кодером и слить 10+ лет жизни за весьма-весьма скромные деньги я не планировал.
Тем не менее, у JB в плане сред разработки есть хорошая, отработанная, модель. Нужно понимать что JB ультраконсервативен — подход всегда один, он идет под копирочку: если есть язык с неким спросом, то на базе IDEA делается IDE которая реализует все то же, что реализовали другие IDE. Кумулятивный опыт дает это сделать быстро и эффективно, а фишечки вроде Котлина дают это сделать еще и приятно (т.к. Java — это фифифи, никто не хочет об нее руки пачкать).
Так вот, после наблюдений за всей этой кухней, у меня сложился свой собственный набор мнений относительно того как надо это делать, что работает а что не работает. Вот список того что мне приходит на ум.
Аппаратно ускоренный редактор
Знаете, мы вот в алготрейдинге не пишем терминалы для обычной виндовой консоли. И оконных приложений не пишем. Почему? Да потому что скорость, что у обычной текстовой консоли (cmd.exe итп) что у оконных приложений — просто шлак. Они тратят больше времени на отрисовку чем на обработку потоков данных. Да, это конечно няшно что виндовая консоль потокобезопасна, но я такое же запилил на коленке, с множественными viewport-ами и буферами. Я на этом собаку съел.
А как надо, спросите вы? Да все просто. Рисуем текстурку на которой ровно 256 буков, ибо использовать юникод не нужно, а языки вроде русского (прости хосподи MOEX) вполне себе в эти 256 влезают. Так вот, на тестурке рисуем каждую из буков, а потом из этой текстурки рендерим каждую букву как прямоугольник на 2D полотне, со всем прекрасным аппаратным ускорением которое нам дают дорогущие видеокарты.
Зачем все это? Да потому что нужна скорость. И она нужна везде. Это бред когда ты редактируешь текст в ИДЕ и у тебя suka залип текстовый редактор! Это просто тотальный бред! Я понимаю что залипания там по вине всяких комплишнов, и что все IDE постепенно прут к zero latency, но я хочу чтобы для рисования одной отдельно взятой буквы не возбуждались, например, подсистемы интерпретации содержания шрифтов. Какая-нть GDI которая делает DrawText()
сливает перформанс настолько, что это даже не смешно, это все тотальный позор.
Кто-то скажет «а как же юникод?» — да в гробу я его видал. Если вы вдруг определили символ дерева через kanji или засунули в код смайлик, мне вас не жалко вообще, используйте Visual Studio или IDEA или что у вас там. И продолжайте лелеять мысль что у вас там «аппаратное ускорение». Ага, щас.
На самом деле, плюсов от текстурно-ориентрированного текст редактора миллион — это в том числе и идеальная плавность скроллинга, возможность очень плавного движения курсора и так далее. Кстати, в моих последних видеокурсах это все представлено как некий рендер — можете посмотреть там превьюшки, и это не предел фантазии!
Короче о чем я — редактирование нужно упрощать и делать аппаратным полностью. Реально много крутого можно сделать, но самое главное это то, что скорость отрисовки феноменальная!
Языковые и source-сервисы
IDE и анализ IDE должны быть разорваны. Ни сервис анализа кода, ни сами сорцы не обязаны лежать локально. И с тем и с тем можно работать удаленно, ибо скорость сетей такая что никакого особого лага не будет. Rider кстати оторвал анализ от редактора, и сделал это весьма успешно через кастомный асинхронный протокол. Но эту идею нужно «дожать» и вынести нафиг это не в отдельный процесс, а в отдельный процесс который может быть где угодно в сети.
Это часть задачи. Другая часть — это сделать весь этот процесс распределенным. Идея о том что только один комп анализирует код, например, или компилирует, или тестирует — это достаточно бредовая идея. Нужная полная распределенность во всем. У нас уже есть примеры вроде IncrediBuild который раскидывает компиляцию по сети, то же самое нужно делать и с анализом и прочими вещами.
Выбор языков программирования
То, что JB сделали все на джаве и сишарпе — это одновременно огромный плюс и огромный косяк. Фразы про «решарпер тормозит» я слышал 5 лет подряд. Если бы в то время не изобрели SSD, вся эта кухня вообще застряла бы в оптимизациях, т.к. на обычных жестких дисках работать со всей этой хитрой инфраструктурой невозможно вообще. Над перформансом там работают постоянно и это, с одной стороны, хорошо, но с другой стороны отчасти виноваты те платформы которые были выбраны для всего этого — JVM и .NET.
В high-performance среде очень важен детерминизм. Вы напарсили 10000 файлов и наплодили временных объектов — кто их будет удалять, и когда? По личному опыту я знаю, что когда нужен перформанс, ты начинаешь жестко копаться во всяких ref struct
, пинить массивы и еще 100500 непотребных вещей.
Да, С++ тяжелый язык и в нем много косяков. Но на нем блин самолеты летают и танкеры плавают! Да, бывают проблемы, язык не совершенен, предостаточно странных решений и немного муторный процесс стандартизации.
Но С++ дает тебе «честные» деструкторы. Он дает как ручной контроль памятью (иногда бывает нужно), так и возможность использовать «умные» указатели. Это намного более предстказуемо чем взять и нааллоцировать тысячу мелких объектов и потом жаловаться что GC делаеть stop-the-world как раз в тот момент когда пользователь пытается вызвать какойнть компшишн.
Еще одна «фишечка» в том, что уйдя на управляемые платформы, мы сразу теряем доступ к таким вещам как микрооптимизации. Такие вещи как использование SIMD или Assembler-ных вставок позволяют реализовывать некоторые вещи не в десятки, а в сотни раз быстрее! Сколько бы не говорили производители этих рантаймов, что JIT заоптимизирует ваши циклы, это все наглая ложь!!! Автоматизация этого происходит только на самых тривиальных, «детских» циклах где все очевидно. Когда у вас появляется хотя бы малейшая зависимость, ваша параллельная или SIMD-овая карета превращается в тыкву.
Особняком стоит ситуация со строками, что какбэ актуально, т.к. в .NET строка — это немутабельная UTF16 конструкция. Это совершенно непрактично по ряду причин. Во-первых, инвариант sizeof(char) == 1
дает возможность детерминированно обходить ASCII-буквы без извратов. То есть, вы прикинули ситуацию? У вас в 99.99999999% случаев только ASCII в коде, но вы платите огромную таксу за то что System.String
реализует весь свой API c допуском что там может быть всякие юникодные corner-cases.
По секрету скажу, что в дотнете у меня для алготрейдинга просто написан тип Str
— это как string
но он строго ASCII, просто держит массив байтов. Естественно, всякие Contains()
становятся вообще тривиальной задачей.
Что еще хорошего от однобайтовых ASCII строк? Да то что они очень хорошо ложатся на GPU. И если вы думаете что GPU тут неприменим, вы просто не научились его готовить — если держать список строк в прямоугольном массиве памяти (представьте себе буфер редактора, ограниченный по горизонтали), то внезапно можно весь этот кусок памяти через P/Invoke скормить CUDA, которая на нем сможет делать такие банальный, казалось бы, вещи как Search & Replace. Это работает не просто «хорошо», это работает офигенно. Особенно на крупных проектах, с которыми, как вы знаете, у всех IDE огромные проблемы, которые не лечатся закупкой RAM-а.
Я могу еще долить про строки если хотите. Помимо юникода, есть еще такая проблема как немутабельность. В частности, эта проблема заставляет многих разработчиков реализовывать свой Substring()
, т.к. фабричный порождает новые строки, а если вам просто хочется некий эфемерный StringRange
, вам придется приготовить его самим, со всеми операторами, конверсиями, набором методов и прочей кухней. Заметьте — вы можете передать ref string
в метод, но вы не можете записать адрес строки в поле. Можно долго извращаться со всем этим, но потом ты понимаешь, что даже со всем запредельным бредом в АПИ, std::string
не так уж и ужасен.
Вообще, в большинстве случаев, мы все равно пишем свой str
(печатать string
слишком долго). Суть заключается в том, чтобы сделать нужные операции как можно дешевыми. В качестве «кустарного» примера можно посмотреть на folly/fbstring.
Аппаратное ускорение
Если мы с вами договорились, что редактор и сорцы/анализ должны находиться в разных местах, то кто мешает на бэк-энде пошаманить еще в направлении анализа кода и всего вот этого? И я сейчас не столько про всякие Optane-ы (хотя хорошее железо тоже нужно), а скорее про специализированные решения в области анализа.
Например, почему бы не загрузить весь working set разработчиков вообще в оперативку? Ну, подумаешь съест там сколько-то гигов на разработчика, всяко анализ пойдет легче пока вам не нужно копать файловую систему со всеми ее ACLами и прочими прелестями. Это кстати и компиляцию тоже ускорит существенно, если что — я например до сих пор, несмотря на то что 2019й на дворе, компилируют крупные вещи вроде Boost на RAM-диске. Ибо нефиг.
Еще одна фишечка это GPGPU, про которые я уже упомянул. Более того, можно не только держать прямоугольные массивы строк, можно также держать базы данных прямо на GPU. Это свежая, развивающаяся область, и там очень много интересного, в т.ч. уже сущестуют коммерческие решения. Представьте себе базу данных, которая ищется в десятки/сотни раз быстрее чем даже если бы она была в RAM полностью.
Касательно FPGA — тут тоже много идей. Одна из них в том, что порой на FPGA очень удобно реализовывать структуры данных. Особенно если это не гигантские но performance-critical структуры. Вообще про FPGA должен наверное быть отдельный разговор т.к. это «темная лошадка» всей этой схемы. Я-то конечно научился уже работать с FPGA-картами через шину PCI (нет ничего сложного если у тебя есть правильный софт), но как получить от них максимальный прирост именно с точки зрения анализа и других девелоперский фич — это вопрос. Одна из идей которые достаточно хорошо раскопаны — это лексеры, т.к. лексический анализ это обычно data-intensive проблема которая очень хорошо ложится на эту архитектуру. Другое дело что лексинг — это только часть общего процесса.
Спекулятивные вычисления и машинное обучение
Как показывает мой проект CallSharp, вполне реально «выводить» подходящий код по набору входных-выходных значений. Я кстати планирую эту тулу допилить до нужного состояния и возможно даже продавать ее, т.к. эта штука реально открыла мне глаза на возможности computer-assisted coding, даже в условиях когда ты делаешь банальный перебор.
Машинное обучение конечно должно идти дальше. Например, я считаю что делать тесты для методов руками — это нонсенс. Если есть некий функционал, мы как минимум должны иметь возможность генерировать для него test scaffolding который потом можно заполнять тестовыми данными. This is low-hanging fruit.
Тут очень сложно предсказать, по какому пути все пойдет. Я например огромный фанат суперкомпиляции — подходу, в котором компьютер выводит по нужным данным цепочку последовательностей комманд. Сейчас это делают, в основном, на микро уровне, т.е. на уровне инструкций процессора. Порой результаты просто ошеломляют — ведь в отличии от человека, компьютер будет напрямую использовать всякий bit twiddling (сдвиги итд.) для того чтобы решить задачу эффективнее.
В идеале, хотелось бы достичь такого состояния, когда компьютер не лексит/парсит на основе описания грамматик, а сам начинает изучать поведение компилятора и на основе этого строит наиболее эффективные структуры для разбора и анализа кода. Вот это то, на что я бы очень хотел посмотреть, но к сожалению «а воз и ныне там» и все видимо занимаются другими, более важными делами.
Заключение
Я не исключаю что мне самому захочется позаниматься чем-то связанным с IDE но если я и буду это делать, то абсолютно все каноны современного ИДЕстроительства будут выкинуты в помойку, т.к., в ретроспективе, понимаешь какое количество родовых травм есть у всех этих систем.
Если коротко, то основные фичи — это
-
Аппаратный рендер текста (плавный скроллинг, анимации итд)
-
Разнесенные на отдельные процессы/компы редактор, компиляторы, анализаторы и все такое
-
Выборочное аппаратное ускорение различных девелопер-специфичных процессов
-
Спекулятивные вычисления — непрерывная компиляция, тестирование и все в этом духе
-
Машинное обучение которое помогает кодить и диагностировать такие ошибки, которые обычные тулы диагностировать не могут
На самом деле, самое интересное — это то о чем я не написал, то есть такие парадигмы работы с кодом, которые мы сами и не знаем. У меня есть некоторые… домыслы, например, что ИДЕ должна вывешивать наружу нечто вроде терминала который обрабатывает комманды типа «добавь класс». Думаете бред? А ничего что любой Autocad уже реализует подобное? Почему такое скриптование есть во всяких 3Д системах но его нет в наших ИДЕ — ума не приложу. Надо сделать.
JB сделали три русских парня со стартовым бюджетом в жалкие $300k. Блин, да я $300k хоть сейчас положу на стол если будет полноценное видение всей этой кухни, понимание как ее реализовывать и талантливые кодеры, которые могут все это заимплементить. Ведь мне кажется что все это поле developer tools точно готово к инновациям и disruption.
Короче надо думать. ■
Оставить комментарий