Статьи

Питер Лоури о VarHandle в JDK9 и создании данных в Java очень быстро

Питер Лори (Peter Lawrey) постоянно работает над расширением границ производительности Java, поэтому на самом деле нет причин, по которым вы не должны отставать от его блога . Я воспользовался возможностью, чтобы догнать Питера в этом месяце по количеству коммитов, которые в настоящее время идут в проект Chronicle-Engine, над которым он работает.

Для начала, просто кратко расскажите о себе и своей текущей работе.

Я — чемпион Java с 20-летним опытом работы в высокопроизводительных Java-приложениях, таких как системы торговли, управления рисками и распределения данных. В своей повседневной работе я являюсь генеральным директором Chronicle Software, которая специализируется на создании программного обеспечения, чтобы действительно быстрые данные были доступны каждому разработчику Java. Я также являюсь основателем группы пользователей Performance Java (1600 участников), и мой блог VanillaJava имеет более 3 миллионов просмотров.

К чему вы и ваши коллеги стремитесь прямо сейчас как цель?

Мы выпустили стабильную версию Chronicle-Engine и надеемся завершить тестирование. Последние несколько лет мы потратили на разработку программного обеспечения для сверхбыстрой передачи данных на Java с нашими ведущими продуктами Chronicle-Queue и Chronicle-Map. Chronicle-Engine — это уровень над Chronicle-Queue и Chronicle-Map, созданный для поддержки виртуализации данных. Целью Chronicle-Engine является упрощение. Разработчики могут использовать стандартный API ConcurrentMap или Pub / Sub, и фактическая реализация абстрагируется и может быть заменена. например, это может быть чисто память, плоские файлы, карта хроники, JDBC, LDAP или пользовательское внутреннее хранилище. Это позволяет разработчикам писать простой код для реактивных сред без необходимости изучать новые API для каждого возможного внутреннего хранилища.Наш API запросов в реальном времени основан на Streams API, где ваши лямбды выполняются на сервере для повышения производительности.

Для обеспечения доступа к данным на всех платформах мы стремимся поддерживать Chronicle Engine в качестве сервера NFS. Это означает, что любой клиент NFS может получить доступ к движку с любого языка.

     # map.put("Hello", "World")

     $ echo World > Hello

     # System.out.println(map.get("MOTD"));

     $ cat MOTD

Примечание. Имя файла — это ключ основного хранилища, а содержимое файла — это значение.

У вас было несколько успешных выступлений на различных конференциях. Какие темы вы обсуждали на конференции в последние два года?

Я говорил о лямбдах в Java 8 и о том, как они круты, в частности о том, как Java 8 JVM может размещать объекты в стеке для автоматического устранения мусора. Мы используем распределенные лямбды, чтобы упростить написание клиентского кода для выполнения на сервере. то есть на клиенте вы используете лямбду, но она отправляется на сервер для выполнения, производительности и атомарности. например

   // print the name of the users 21 or over, including as users added.

   map.entrySet().query()

          .filter(e -> e.getValue().getAge() >= 21) // executed on the server

          .map(e -> e.getKey())   // executed on the server

          .subscribe(System.out::println); // executed on the client.

Я также говорил о хранении очень больших наборов данных в Java с использованием собственной памяти. Например, один клиент содержит 70 ГБ данных в Java с условным использованием кучи. После перезапуска процесса предоставление всех этих данных добавляет всего 10 миллисекунд. У нас есть два клиента, которые сохраняют данные с максимальной скоростью более 10 миллионов событий в секунду без потери сообщений.

Какие вопросы вы часто получаете на своих презентациях и от сообщества?

Самый распространенный вопрос — насколько велика компания и где находится наш офис. У нас 4 штатных разработчика и 4 штатных сотрудника. Мы либо работаем дома, либо на месте.

Есть ли что-то, что вы действительно следите за Java 9, связанное с работой, которую вы делаете?

Большая вещь для меня — VarHandle. Как это будет работать для поточно-ориентированной памяти кучи, учитывая, что мы так много используем? Мы все еще можем использовать Unsafe в Java 9, но лучше иметь стандартный API для работы. Еще лучше было бы определить пользовательские встроенные функции, возможно, в Java 10. Это было бы действительно здорово.

Говоря о Java 9, что вы думаете о планах по переносу функциональности sun.misc.Unsafe на общедоступный API Java в Java 9, который получил широкую известность в последние пару недель?

Проблема, как я вижу, состоит в том, что они планируют удалить что-то без замены — или, по крайней мере, замены, в которой мы можем быть уверены (это даже не в версии EA 9 для EA).

Они убрали tools.jar, но API компилятора существует с Java 6, так что это не должно быть проблемой.

Другая проблема заключается в том, что дизайнеры не очень понимают, почему Unsafe использовался в первую очередь. Они знают, что он использовался, но считают, что его никогда не следовало использовать, и они единственные, кому это когда-либо нужно было. Мы могли бы использовать JNI, но сделать это действительно безопаснее?

Есть ли какие-нибудь интересные или полезные технологии, о которых вы узнали за последние пару месяцев, о которых вы хотите поговорить?  

Я думаю, что два проекта со временем стали более впечатляющими. Это JITWatch, который позволяет вам увидеть, как процесс компилируется, вплоть до машинного кода для строки Java. Другой — это JMH, который значительно облегчил написание микропроцессоров. Они уже давно, но последние обновления означают, что вы должны взглянуть на них по-другому.

Или просто любая другая тема, которая, на ваш взгляд, интересна сейчас, о которой вы еще не говорили?

Я думаю, стоит повторить, насколько важен анализ Inlining и Escape. В сочетании они могут перемещать недолговечный объект в стек или даже полностью исключать его. Это важно для производительности Stream API с Lambdas, но оно работает для всех объектов Java. Короткоживущие объекты, которых вы могли бы избежать в прошлом, могут не иметь значения (по крайней мере, после разогрева JVM). С точки зрения низкой задержки это важно, поскольку это означает, что вы можете снова использовать объекты, если JVM может их устранить.