
Антонио Куни — инженер, давно занимающийся повышением производительности Python, а также разработчик PyPy. Он провёл на EuroPython 2025Читать полностью »

Антонио Куни — инженер, давно занимающийся повышением производительности Python, а также разработчик PyPy. Он провёл на EuroPython 2025Читать полностью »
При создании компилятора для собственного языка программирования я сделал его как транспайлер в исходный код на С++, вот только реализация сильно подкачала. Сначала приходится генерировать динамическую библиотеку с помощью вызова gcc, который и сам по себе не очень быстрый, так еще его может и не быть на целевой машине, особенно на другой платформе (например Windows). Конечно, для первых экспериментов и такой реализации было достаточно, но сейчас, когда я начал готовить код компилятора к публикации, стало понятно, что текущий вариант с фоновым запуском gcc никуда не годится.
Из-за этого, я решил не откладывать перевод компилятора на использование LLVM, который планировался когда нибудь в будущем, а решил сделать это уже сейчас. И для этого нужно было научиться запускать компиляцию C++ кода с помощью библиотек Clang, но тут вылезло сразу несколько проблем.
Оказывается, интерфейс Clang меняется от версии к версии и все найденные мной примеры были старыми и не запускались в актуальной версии (Сlang 12), а стабильный C-style интерфейс предназначен для парсинга и анализа исходников и с помощью которого сгенерировать исполняемые файлы не получится*.
Дополнительная проблемой оказалось, что Clang не может анализировать файл из памяти, даже если для этого есть соответствующие классы. Из объяснений выходило, что в экземпляре компилятора проверяется, является ли ввод файлом**.
А теперь публикую результат своих изысканий в виде рабочего примера динамической компиляции С++ кода с последующей его загрузкой и выполнением скомпилированных функций. Исходники адаптированны под актуальную версию Clang 12. Пояснения к коду я перевел и дополнил перед публикацией, а ссылки на исходные материалы приведены в конце статьи.

От переводчика: GraalVM — новая, интересная технология, но на Хабре по ней не так много статей, которые бы могли показать примеры возможностей Graal. Статья ниже — это не просто перечисление того, что GraalVM умеет, но ещё и небольшой мастер-класс, аналогичный тому, который Chris Seaton и Олег Шелаев проводили на Oracle CodeOne 2018. Вслед за автором, призываю — пробуйте делать примеры из статьи, это действительно интересно.
В GraalVM много всего разного, и, если вы слышали это название раньше, или даже видели доклады, то все равно есть много вещей, о которых вы наверняка ещё не знаете, но которые GraalVM может делать. В этой статье мы рассмотрим разнообразные возможности, которые предоставляет GraalVM и покажем, что с их помощью можно сделать.
Предлагаю посмотреть все то, что стоит за простыми строками инициализации объектов, вызова методов и передачи параметров. Ну и, разумеется, использование этих сведений на практике — вычитывание стека вызывающего метода.
Прежде, чем приступить к повествованию, настоятельно рекомендую ознакомиться с первым постом про StructLayout, т.к. там разобран пример, который будет использоваться в этой статье.
Весь код, кроющийся за высокоуровневым, представлен для режима отладки, именно он показывают концептуальную основу. JIT оптимизации — это отдельная и большая тема, которая здесь рассматриваться не будет.
Также хотелось бы предупредить, что данная статья не содержит материал, который стоит применять в реальных проектах.
Любой код в конечном итоге становится набором машинных комманд. Наиболее понятно их представление в виде инструкций языка Ассемблера, прямо соответсвующих одной (или нескольким) машинным инструкциям.

Разбор последней четвёртой задачи:
public double octaPow(double a) {
return Math.pow(a, 8);
}
public double octaPow(double a) {
return a * a * a * a * a * a * a * a;
}
public double octaPow(double a) {
return Math.pow(Math.pow(Math.pow(a, 2), 2), 2);
}
public double octaPow(double a) {
a *= a; a *= a; return a * a;
}
Условие (упрощённо):
Определить, какие методы быстрые, а какие — медленные (JRE 1.8.0_161).
Под катом бенчмарки, куски ассемблера и разбор оптимизаций со стороны JVM.
Другие публикации серии: Часть 1, Часть 2 и Часть 3.
Читать полностью »
Интринсик или intrinsic-функция — функция, которую JIT-компилятор может встроить вместо вызова Java- и JNI-кода с целью оптимизации. Важный вывод из этого — intrinsic-функции не доступны в режиме интерпретатора. По умолчанию в HotSpot используется два JIT-компилятора C1 и C2, таким образом, может быть доступна реализация intrinsic-функции для каждого из JIT-компиляторов. Различия в реализации intrinsic-функций для разных JIT-компиляторов обуславливаются различным внутренним представлением кода (intermediate representation — IR).
В HotSpot реализовано несколько сотен интринсиков (их количество растёт от релиза к релизу). Описание всех intrinsic-функций можно найти в исходниках OpenJDK в файле vmSymbols.hpp. Ниже приведены полные списки интринсиков для JDK 7 (vmSymbols.hpp), JDK 8 (vmSymbols.hpp), JDK 9 (vmSymbols.hpp) и JDK 10 (vmSymbols.hpp).
Читать полностью »
Публикую предпоследнюю часть разбора с третьей задачей. До этого выходил разбор первой задачи и второй задачи.
Код к третьей задаче:
public static double compute(
double x1, double y1, double z1,
double x2, double y2, double z2) {
double x = y1 * z2 - z1 * y2;
double y = z1 * x2 - x1 * z2;
double z = x1 * y2 - y1 * x2;
return x * x + y * y + z * z;
}
public static double compute(
double x1, double y1, double z1,
double x2, double y2, double z2) {
Vector v1 = new Vector(x1, y1, z1);
Vector v2 = new Vector(x2, y2, z2);
return v1.crossProduct(v2).squared();
}
public final static class Vector {
private final double x, y, z;
public Vector(double x, double y, double z) {
this.x = x; this.y = y; this.z = z;
}
public double squared() {
return x * x + y * y + z * z;
}
public Vector crossProduct(Vector v) {
return new Vector(
y * v.z - z * v.y,
z * v.x - x * v.z,
x * v.y - y * v.x);
}
}
Условие (упрощённо):
Определить, какие методы быстрые, а какие — медленные (JRE 1.8.0_161).
На главной сибирской Java-конференции JBreak-2018, проходившей в Новосибирске, Christian Thalinger из Twitter поделился практическим опытом использования Graal. Этот доклад мы слушали всей рабочей группой в полном составе. Вполне объяснимо, если учесть тот факт, что Graal по-прежнему считается смелым и потенциально опасным экспериментом (хотя очень похоже, что он войдёт в JDK 10). Было очень интересно узнать, как эта новинка проявляет себя в бою — да не где-нибудь, а в разработке такого уровня.

Кристиан Талингер десяток с лишним лет работает с виртуальными машинами Java, причём ключевой навык в его экспертизе — как раз JIT-компиляторы. Именно Кристиан внедрил Graal и стал инициатором его нынешнего (весьма, по словам Криса, активного) использования в продакшн-среде Twitter. И, если верить Талингеру, это нововведение сохраняет компании приличные деньги за счёт экономии железных ресурсов.
Читать полностью »
Первая часть — разбор самой холиварной задачи из четырёх:
void forEach(List<Integer> values, PrintStream ps) {
values.forEach(ps::println);
}
void forEach(List<Integer> values, PrintStream ps) {
values.stream().forEach(ps::println);
}
void forEach(List<Integer> values, PrintStream ps) {
values.parallelStream().forEach(ps::println);
}
Под катом условие задач, история их появления, а также разбор первой задачи и статистика её правильных решений среди участников конференции.
Читать полностью »
Вот и наступила осень. Кто-то возвращается в город с центнером яблок в багажнике, кто-то — c норвежским пивом прямиком с JavaZone, а мы подготовили для вас материал, который, надеемся, скоротает дождливые вечера. Мы расскажем о трёх летних встречах JUG.ru. Посему разработчики, вернувшись из отпусков, имеют замечательную возможность запастись чашкой горячего чая, завернуться в плед и посмотреть видео с наших митапов.
Итак, летом у нас было три встречи:
— Douglas Hawkins из Azul рассказал об особенностях работы JIT-компиляторов в HotSpot JVM;
— Alvaro Hernandez, разработчик ToroDB, рассказал о том, как Java работает с PostgreSQL;
— наконец, Евгений Борисов порадовал нас новой порцией загадок на тему Spring.