19 июл. 2021 г.

IntelliJ Kotlin plugin internals: On-the-flight diagnostics reporting

Background

Highlighting of a Kotlin file prior to Kotlin 1.5 (and Kotlin IntelliJ plugins based on Kotlin before 1.5) in oversimplified way was sequential:
  • run a compiler for a kotlin file
  • collects diagnostics (i.e. errors and warnings) for each PSI element
  • highlight them in a file

Goal

Provide feedback on compilation errors (or warning) as soon as possible.

Impl, details and trade-offs

The biggest concern in a provided highlighting process:

why we have to wait till the end of kotlin file analysis to show errors and warnings?

If you ever compile some file in a console using gcc or javac directly (w/o make or any other build managers), you definitely recall that compilers print diagnostic messages during compilation while entire compilation process for a single file could takes some seconds more.

12 апр. 2018 г.

Guava, Graal and Partial Escape Analysis

Recently java 10 release happened - in fact, Graal was available earlier, but now it is more easy to access and use it - Congratulations, you're running #Graal! - just add a couple options:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
What does it can provide for us and what kind of enhancements we can expect to get, and more over - what dirty-hacks could be dropped ?

29 мар. 2018 г.

build hsdis with Java 10 on MacOsX

instructions to build hsdis with java 10 - based on instructions for building hsdis on OSX (with java 9)
$ hg clone http://hg.openjdk.java.net/jdk/jdk10/
$ cd jdk10/src/utils/hsdis
$ wget https://ftp.gnu.org/gnu/binutils/binutils-2.28.tar.bz2 
$ tar jxf binutils-2.28.tar.bz2
$ make BINUTILS=binutils-2.28 ARCH=amd64
$ sudo cp build/macosx-amd64/hsdis-amd64.dylib /Library/Java/JavaVirtualMachines/jdk-10.jdk/Contents/Home/lib/server
Note: despite of hsdis/README it does NOT compile with binutils-2.17, nor binutils-2.19.1 neither with latest binutils-2.30. binutils-2.28 works fine on High Sierra.

5 февр. 2016 г.

Java unsafe: copyMemory aligned vs unaligned

Давеча переводя проект на новые рельсы стала падать сборка - тесты проходят, а вот jvm крешится.

Первое подозрение упало на наш alloc / dealloc поверх Unsafe (да-да, кровь-кишки-камаз) - но в итоге все же стало ясно, что наши руки чистые и вина реально на C2 компиляторе и трова стала тому причина - на эту тему две ошибки в C2 компиляторе: JDK-8081379 и по мотивам этого же JDK-6675699.

Однако, пока я винил наш alloc/dealloc смотрел - а не пытаемся ли мы деаллоцировать чего не нужного, соответственно стал писать адреса выделенной памяти и размеры.
Удивило, что очень много объектов без выравнивания по длине - например, 27 байт или там 253.

Читаем sun.misc.Unsafe#copyMemory и тут ребята заботливо пишут:
    /**
     * Sets all bytes in a given block of memory to a copy of another
     * block.
     *
     * This method determines each block's base address by means of two parameters,
     * and so it provides (in effect) a double-register addressing mode,
     * as discussed in {@link #getInt(Object,long)}.  When the object reference is null,
     * the offset supplies an absolute base address.
     *
     * The transfers are in coherent (atomic) units of a size determined
     * by the address and length parameters.  If the effective addresses and
     * length are all even modulo 8, the transfer takes place in 'long' units.
     * If the effective addresses and length are (resp.) even modulo 4 or 2,
     * the transfer takes place in units of 'int' or 'short'.
     *
     * @since 1.7
     */


Более того, мистер Коваль накинул еще:
мол не только же длина, но и смещение играют роль - н.р если даже читать long, но он будет смещен на 1 байт относительно слова - то в итоге будут прочитаны два long.


обновление 2015-02-13:

Итак, куда же идет Unsafe.copyMemory ?

Это нативный jvm вызов:
копаем в сторону unsafe.cpp: Unsafe_CopyMemory
потом Copy::conjoint_memory_atomic

и вот от момент откровения:

  uintptr_t bits = (uintptr_t) src | (uintptr_t) dst | (uintptr_t) size;

  if (bits % sizeof(jlong) == 0) {
    Copy::conjoint_jlongs_atomic((jlong*) src, (jlong*) dst, size / sizeof(jlong));
  } else if (bits % sizeof(jint) == 0) {
    Copy::conjoint_jints_atomic((jint*) src, (jint*) dst, size / sizeof(jint));
  } else if (bits % sizeof(jshort) == 0) {
    Copy::conjoint_jshorts_atomic((jshort*) src, (jshort*) dst, size / sizeof(jshort));
  } else {
    // Not aligned, so no need to be atomic.
    Copy::conjoint_jbytes((void*) src, (void*) dst, size);
  }
Если кратко, то bits тогда и только тогда будет кратен размеру long, когда и адрес источника, и адрес цели, и длина блока будут кратны размеру long.

benchmark.
проверяет копирование в многопоточном режиме - 4 нитки.

Изначально производилось копирование из одного общего (для всех нитей) куска памяти в другой общий кусок памяти - и от этого получались странные цифры, что копирование 8 байт со смещением 0 такое же, как и копирование 8 байт со смещением 3 байта.

В моем приложении другой шаблон использования - копирование происходит из общего куска памяти в свой (н-р локальный массив байт) локальный кусок памяти.

Результаты для 4х ниток:

Benchmark                    Mode  Samples   Score   Error  Units
copyMemory253Bytes           avgt       15  13.023 ± 0.376  ns/op
copyMemory253BytesOffset3    avgt       15  13.189 ± 0.512  ns/op
copyMemory256Bytes           avgt       15  11.091 ± 0.304  ns/op
copyMemory256BytesOffset7    avgt       15  13.185 ± 0.066  ns/op

copyMemory27Bytes            avgt       15   9.034 ± 0.058  ns/op
copyMemory32Bytes            avgt       15   5.567 ± 0.154  ns/op
copyMemory32BytesOffset3     avgt       15   7.779 ± 0.080  ns/op

copyMemory4Bytes             avgt       15   6.801 ± 0.068  ns/op
copyMemory4BytesOffset3      avgt       15   7.760 ± 0.091  ns/op

copyMemory8Bytes             avgt       15   6.763 ± 0.044  ns/op
copyMemory8BytesOffset1      avgt       15   8.398 ± 0.154  ns/op
copyMemory8BytesOffset3      avgt       15   8.368 ± 0.083  ns/op
copyMemory8BytesOffset5      avgt       15   8.396 ± 0.079  ns/op

readByteOffset0              avgt       15   3.067 ± 0.153  ns/op
readByteOffset3              avgt       15   3.024 ± 0.044  ns/op

readIntOffset0               avgt       15   3.001 ± 0.037  ns/op
readIntOffset3               avgt       15   3.051 ± 0.150  ns/op

readLongOffset0              avgt       15   2.997 ± 0.042  ns/op
readLongOffset3              avgt       15   2.993 ± 0.056  ns/op
и для 1 нитки
Benchmark                    Mode  Samples   Score   Error  Units
copyMemory253Bytes           avgt       15  13.392 ± 0.580  ns/op
copyMemory253BytesOffset3    avgt       15  12.903 ± 0.304  ns/op
copyMemory256Bytes           avgt       15  11.195 ± 0.405  ns/op
copyMemory256BytesOffset7    avgt       15  13.446 ± 0.422  ns/op

copyMemory27Bytes            avgt       15   9.136 ± 0.266  ns/op
copyMemory32Bytes            avgt       15   5.513 ± 0.190  ns/op
copyMemory32BytesOffset3     avgt       15   7.830 ± 0.273  ns/op

copyMemory4Bytes             avgt       15   6.826 ± 0.204  ns/op
copyMemory4BytesOffset3      avgt       15   7.757 ± 0.223  ns/op

copyMemory8Bytes             avgt       15   6.897 ± 0.221  ns/op
copyMemory8BytesOffset1      avgt       15   8.534 ± 0.276  ns/op
copyMemory8BytesOffset3      avgt       15   8.482 ± 0.285  ns/op
copyMemory8BytesOffset5      avgt       15   8.403 ± 0.262  ns/op

readByteOffset0              avgt       15   2.971 ± 0.104  ns/op
readByteOffset3              avgt       15   3.009 ± 0.115  ns/op

readIntOffset0               avgt       15   3.001 ± 0.125  ns/op
readIntOffset3               avgt       15   3.032 ± 0.113  ns/op

readLongOffset0              avgt       15   3.010 ± 0.100  ns/op
readLongOffset3              avgt       15   3.060 ± 0.094  ns/op
Т.е действительно для копирования очень важно, чтобы всё было по восьмерке, тогда как для чтения это не имеет значения. ... meten is weten // голл. поговорка: измерение это знание

27 мар. 2013 г.

java: конференция jpoint

Осталось чуть больше недели до независимой java конференции jpoint, организованной энтузиастами Java User Group, которая состоится 5го апреля 2013 года в конгрессном центре “ПетроКонгресс” по адресу Санкт-Петербург, ул. Лодейнопольская, д. 5.



Святые угодники! Кто все эти люди ?!?

Я буду рассказывать о шишках и фишках, которые мы набили с garbage collectorом, как мы научились не мешать друг другу работать, зачем родился на свет garbage free logger, а так же о своих наблюдениях и рекомендациях в оптимизации приложений с оглядкой на gc, которые, надеюсь, будут полезные другим разработчикам.

Организаторы сознательно сделали несколько шагов объявив конференцию для middle/senior разработчиков:
  • Участие для слушателей в конференции платное. Деньги не космические, но это создаёт порог отсева толпы, пришедшей за халявой в виде бесплатных ручек и блокнотов
  • Подбор тем докладов и самих докладчиков: определённо темы докладов для людей «глубоко женатых», т.е для тех, у кого за плечами гораздо больше, чем hello world и пары свистелок.

Мой предварительный план докладов, которые хочу послушать:
  • Динамическое обнаружение гонок в многопоточных Java-программах - ребята из Devexperts, явно есть чему поучиться у них и узнать новые способы варки автогеномтонкой работы в java
  • Java Runtime: повседневные обязанности виртуальной машины Java - очень мне близка тематика по духу, приятно удивлён, что и у нас есть горячие головы, которые лобзиком выпиливают gc из jvm.
  • и быть может, холивное Eclipse vs Intellij IDEA
  • хотел бы ещё сходить послушать GC: Friend or foe, но ведь не дадут послушать...

Ещё раз хотелось бы послать лучи поддержки организаторам - у нас всё получится !

Дополнение. Организаторы обещают сделать видеозаписи докладов, которые после будут доступны в интернетах. Не спрашивайте меня когда, сколько и по чём.

P.S. Да, и регистрация уже закрыта.

28 февр. 2013 г.

java: who has eaten my cpu ?

Приходит давеча коллега и показывает запущенное простенькое java приложение, которое выжирает > 100% cpu без какой-либо на то видимой причины.

Святые угодники! что делать ?

3 янв. 2013 г.

Задачка: Перестановки в массиве

Дан массив
[ a1, a2, ... an, b1, b2, ... bn ]

Необходимо переставить элементы в массиве, так, чтобы получился

[ a1, b1, a2, b2, ... an, bn ]

замечание: дополнительная память O(1), сложность < O(n2)

20 дек. 2012 г.

Задачка: зеркально отразить битовое представление

Как можно зеркально отобразить битовое представление 8 битного числа ? 16 битного числа ?

Например,
M(12310) = M(011110112) = 110111102 = 22210.

внимание! комментарии содержат ответ.

27 нояб. 2012 г.

java: Adaptive throttling, Part 1


Типичная проблема, которая возникает при обработке большого потока сообщений:

- нельзя пропихнуть большого слона через маленькую трубу, т.е. обработка сообщений не успевает «проглотить» все сообщения


При этом существуют некоторые ограничения на поток данных :

  • поток не равномерный и состоит из событий разного типа
  • количество типов событий заранее не известно, но конечное число
  • каждый тип события имеет свою актуальность во времени
  • все типы событий имеют равный приоритет

На диаграмме приведён пример разрешения проблемы: нагребатор™ работает на нитке T1, а следовательно разгребатор™ на нитке T2
  • за время обработки события типа A успевают прийти новые события как типа B, так и A
  • после обработки события типа B необходимо обработать наиболее актуальное событие типа A

Проблема осложняется ещё тем, что может быть несколько нагребаторов™, при этом каждый нагребатор™ может порождать только события одного типа; так и есть потребность в нескольких разгребаторах™ - при этом

Терминология. Stream есть поток данных, тогда как thread есть нитка или нить выполнения. И не стоит путать потоки с нитками.

14 нояб. 2012 г.

java: nanoTime

Пока одни заливали соляру в трактор, мы продолжаем копаться в своём.

Тёма очень хорошо написал о измерении времени в java с ссылками на источники, так, что казалось бы и добавить нечего, но вставлю я свои пять копеек.

Все мы хорошо знаем метод System.nanoTime()

Задачка: развернуть односвязанный список

Задан односвязанный список, например:

A -> B -> C -> ... -> X -> Y -> Z

Необходимо развернуть список, т.е, чтобы его крайний элемент стал первым, предпоследний вторым, и т.д, и в конце концов, первый элемент стал бы крайним элементом.

Z -> Y -> X -> ... -> C -> B -> A

Сложность: O(N), доступная память: O(1).

замечание: можно модифицировать исходный список.

внимание! комментарии содержат ответ.

java: garbage less

За время написания gflogger и борьбой за low latency в java накопился некоторый опыт о том как меньше плодить мусора и тем самым меньше нагружать сборщик мусора, и как следствие, меньше влиять на производительность самого приложения.

Такому тонкому троллиподходу придумали специальный термин garbage less design.

Впрочем, существую и некоторые другие вариации как заставить garbage collector меньше мешать нам жить.

31 окт. 2012 г.

Paragliding: U-Turn Blacklight

Добрых шесть лет верой и правдой служил мне мой крыл - триколор U-Turn Infinity II. Где мы только с ним не побывали, в каких жоусловиях не бывали, но его время пришло. Тем более, что летом на Юце имелась чудесная возможность немного попробовать U-Turn Blacklight (удлинение 5.8, качество 10.5) - и надо сказать, что его скорость просто впечатлила . Вполне очевидно, что драгдиллер сделал предложение от которого я не смог удержаться - и крыл был заказан.

Ранее уже опробовал obsession - как в динамике, так и в термичке. Надо сказать, что первый полёт мне больше всего запомнился, и прежде всего хлопаньем ушей, что впрочем никак не отражалось на безопасности или управляемости крыла.

И вот настал долгожданный момент - пришёл мой крыл в желаемой не серийной расцветке

lime/black/white

9 окт. 2012 г.

Задача №377

Задача №377:

Белка массой 0.5 кг сидит на абсолютно гладкой, обледенелой, горизонтальной, плоской крыше. Человек бросает белке камень массой 0.1 кг. Камень летит горизонтально со скоростью 6 м/с. Белка хватает камень и удерживает его.

Вычислите скорость белки, поймавшей камень.

внимание! комментарии содержат ответ.

1 окт. 2012 г.

Задачка: Объём луж

На рельеф некоторой местности падает дождь, попадая в низменности он образует лужи и озерца.

Найти объём образовавшихся луж за время O(N).

замечание №1: силами поверхностного натяжения пренебречь.

замечание №2: рельеф задан целыми числами

например:
V([0, 0, 3, 6, 6, 10, 5, 5, 5, 7, 7, 4, 9, 9, 13, 12, 14, 4, 3, 0]) = 30.

20 сент. 2012 г.

gflogger 0.0.9.x



Garbage Free Logger добрался до версии 0.0.9.x .

Надо сказать, что версия полна изменениями, допиливаниями и добавлением мелких, но важных мелочей, которые активно используются.

Но обо всём по порядку.

19 сент. 2012 г.

Задачки: Количество сообщений в минуту

Есть некоторый поток сообщений, идущий не равномерно.

Например, с 0 - 10 секунду может прийти 1 сообщение, в следующие 10 ещё 5, потом 10, потом 100 и т.д и опять наступит затишье.

В целях мониторинга хочется иметь представление о точном количестве полученных сообщений (скользящим окном) за крайнюю минуту.

Пояснение: если мы запрашиваем кол-во сообщений в 13:12:05, то должны получить кол-во сообщений с 13:11:05 по 13:12:05. Запрос в 13:12:57 отображает число сообщений с 13:11:57 по 13:12:57.

При этом не интересует сколько было получено две минуты назад, только реальные актуальные цифры. Допускается огрубление с точностью до секунды.

Ограничения: память O(1), сложность O(1), одна нитка выполнения.

p.s. я не знаю, существует ли какое-то классическое и/или единственно верное решение или нет, уже засыпая я смог придумать вполне приемлемое для меня решение, но которое расходует больше, чем 3-5 переменных.